diff --git a/pkg/kapis/resources/v1alpha3/handler.go b/pkg/kapis/resources/v1alpha3/handler.go index 520b10590a2e99b03bfdba134b6b350a0905ce75..5558c2fd060f65a251c9376ace6e941d232f9520 100644 --- a/pkg/kapis/resources/v1alpha3/handler.go +++ b/pkg/kapis/resources/v1alpha3/handler.go @@ -28,6 +28,36 @@ func New(factory informers.InformerFactory) *Handler { } } +func (h *Handler) handleGetResources(request *restful.Request, response *restful.Response) { + namespace := request.PathParameter("namespace") + resourceType := request.PathParameter("resources") + name := request.PathParameter("name") + + result, err := h.resourceGetterV1alpha3.Get(resourceType, namespace, name) + if err == nil { + response.WriteEntity(result) + return + } + + if err != resource.ErrResourceNotSupported { + klog.Error(err) + api.HandleInternalError(response, nil, err) + return + } + + // fallback to v1alpha2 + resultV1alpha2, err := h.resourcesGetterV1alpha2.GetResource(namespace, resourceType, name) + + if err != nil { + klog.Error(err) + api.HandleInternalError(response, nil, err) + return + } + + response.WriteEntity(resultV1alpha2) + +} + // handleListResources retrieves resources func (h *Handler) handleListResources(request *restful.Request, response *restful.Response) { query := query.ParseQueryParameter(request) diff --git a/pkg/kapis/resources/v1alpha3/register.go b/pkg/kapis/resources/v1alpha3/register.go index 7d462bdfa8550c7907a9debd9fa3c59672ba96cb..cb4d6cad567f04acbc087486539f7f3adab94d8a 100644 --- a/pkg/kapis/resources/v1alpha3/register.go +++ b/pkg/kapis/resources/v1alpha3/register.go @@ -70,6 +70,15 @@ func AddToContainer(c *restful.Container, informerFactory informers.InformerFact Param(webservice.QueryParameter(query.ParameterOrderBy, "sort parameters, e.g. orderBy=createTime")). Returns(http.StatusOK, ok, api.ListResult{})) + webservice.Route(webservice.GET("/namespaces/{namespace}/{resources}/{name}"). + To(handler.handleGetResources). + Metadata(restfulspec.KeyOpenAPITags, []string{tagNamespacedResource}). + Doc("Namespace level get resource query"). + Param(webservice.PathParameter("namespace", "the name of the project")). + Param(webservice.PathParameter("resources", "namespace level resource type, e.g. pods,jobs,configmaps,services.")). + Param(webservice.PathParameter("name", "the name of resource")). + Returns(http.StatusOK, ok, api.ListResult{})) + webservice.Route(webservice.GET("/components"). To(handler.handleGetComponents). Metadata(restfulspec.KeyOpenAPITags, []string{tagComponentStatus}). diff --git a/pkg/models/resources/v1alpha3/persistentvolumeclaim/persistentvolumeclaim.go b/pkg/models/resources/v1alpha3/persistentvolumeclaim/persistentvolumeclaim.go new file mode 100644 index 0000000000000000000000000000000000000000..6f9f9934248d56add877a18546fa85e6305a6826 --- /dev/null +++ b/pkg/models/resources/v1alpha3/persistentvolumeclaim/persistentvolumeclaim.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 persistentvolumeclaim + +import ( + snapshotinformers "github.com/kubernetes-csi/external-snapshotter/v2/pkg/client/informers/externalversions" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/informers" + "kubesphere.io/kubesphere/pkg/api" + "kubesphere.io/kubesphere/pkg/apiserver/query" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3" + "strconv" + "strings" +) + +const ( + storageClassName = "storageClassName" + + annotationInUse = "kubesphere.io/in-use" + annotationAllowSnapshot = "kubesphere.io/allow-snapshot" + annotationStorageProvisioner = "volume.beta.kubernetes.io/storage-provisioner" +) + +type persistentVolumeClaimGetter struct { + informers informers.SharedInformerFactory + snapshotInformers snapshotinformers.SharedInformerFactory +} + +func New(informer informers.SharedInformerFactory, snapshotInformer snapshotinformers.SharedInformerFactory) v1alpha3.Interface { + return &persistentVolumeClaimGetter{informers: informer, snapshotInformers: snapshotInformer} +} + +func (p *persistentVolumeClaimGetter) Get(namespace, name string) (runtime.Object, error) { + pvc, err := p.informers.Core().V1().PersistentVolumeClaims().Lister().PersistentVolumeClaims(namespace).Get(name) + if err != nil { + return pvc, err + } + p.annotatePVC(pvc) + return pvc, nil +} + +func (p *persistentVolumeClaimGetter) List(namespace string, query *query.Query) (*api.ListResult, error) { + all, err := p.informers.Core().V1().PersistentVolumeClaims().Lister().PersistentVolumeClaims(namespace).List(query.Selector()) + if err != nil { + return nil, err + } + + var result []runtime.Object + for _, pvc := range all { + p.annotatePVC(pvc) + result = append(result, pvc) + } + return v1alpha3.DefaultList(result, query, p.compare, p.filter), nil +} + +func (p *persistentVolumeClaimGetter) compare(left, right runtime.Object, field query.Field) bool { + leftSnapshot, ok := left.(*v1.PersistentVolumeClaim) + if !ok { + return false + } + rightSnapshot, ok := right.(*v1.PersistentVolumeClaim) + if !ok { + return false + } + return v1alpha3.DefaultObjectMetaCompare(leftSnapshot.ObjectMeta, rightSnapshot.ObjectMeta, field) +} + +func (p *persistentVolumeClaimGetter) filter(object runtime.Object, filter query.Filter) bool { + pvc, ok := object.(*v1.PersistentVolumeClaim) + if !ok { + return false + } + + switch filter.Field { + case query.FieldStatus: + return strings.EqualFold(string(pvc.Status.Phase), string(filter.Value)) + case storageClassName: + return pvc.Spec.StorageClassName != nil && *pvc.Spec.StorageClassName == string(filter.Value) + default: + return v1alpha3.DefaultObjectMetaFilter(pvc.ObjectMeta, filter) + } +} + +func (p *persistentVolumeClaimGetter) annotatePVC(pvc *v1.PersistentVolumeClaim) { + inUse := p.countPods(pvc.Name, pvc.Namespace) + isSnapshotAllow := p.isSnapshotAllowed(pvc.GetAnnotations()[annotationStorageProvisioner]) + if pvc.Annotations == nil { + pvc.Annotations = make(map[string]string) + } + pvc.Annotations[annotationInUse] = strconv.FormatBool(inUse) + pvc.Annotations[annotationAllowSnapshot] = strconv.FormatBool(isSnapshotAllow) +} + +func (p *persistentVolumeClaimGetter) countPods(name, namespace string) bool { + pods, err := p.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 +} + +func (p *persistentVolumeClaimGetter) isSnapshotAllowed(provisioner string) bool { + if len(provisioner) == 0 { + return false + } + volumeSnapshotClasses, err := p.snapshotInformers.Snapshot().V1beta1().VolumeSnapshotClasses().Lister().List(labels.Everything()) + if err != nil { + return false + } + for _, volumeSnapshotClass := range volumeSnapshotClasses { + if volumeSnapshotClass.Driver == provisioner { + return true + } + } + return false +} diff --git a/pkg/models/resources/v1alpha3/persistentvolumeclaim/persistentvolumeclaim_test.go b/pkg/models/resources/v1alpha3/persistentvolumeclaim/persistentvolumeclaim_test.go new file mode 100644 index 0000000000000000000000000000000000000000..3a7dc675182ca5a9f61db231ee97c2386ee0eeed --- /dev/null +++ b/pkg/models/resources/v1alpha3/persistentvolumeclaim/persistentvolumeclaim_test.go @@ -0,0 +1,251 @@ +/* + + 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 persistentvolumeclaim + +import ( + "github.com/google/go-cmp/cmp" + snapshot "github.com/kubernetes-csi/external-snapshotter/v2/pkg/apis/volumesnapshot/v1beta1" + snapshotefakeclient "github.com/kubernetes-csi/external-snapshotter/v2/pkg/client/clientset/versioned/fake" + snapshotinformers "github.com/kubernetes-csi/external-snapshotter/v2/pkg/client/informers/externalversions" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes/fake" + "kubesphere.io/kubesphere/pkg/api" + "kubesphere.io/kubesphere/pkg/apiserver/query" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3" + "testing" +) + +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", + "default", + &query.Query{ + Pagination: &query.Pagination{ + Limit: 10, + Offset: 0, + }, + SortBy: query.FieldName, + Ascending: false, + Filters: map[query.Field]query.Value{query.FieldNamespace: query.Value("default")}, + }, + &api.ListResult{ + Items: []interface{}{pvc3, pvc2, pvc1}, + TotalItems: len(persistentVolumeClaims), + }, + nil, + }, + { + "test status filter", + "default", + &query.Query{ + Pagination: &query.Pagination{ + Limit: 10, + Offset: 0, + }, + SortBy: query.FieldName, + Ascending: false, + Filters: map[query.Field]query.Value{ + query.FieldNamespace: query.Value("default"), + query.FieldStatus: query.Value(pvc1.Status.Phase), + }, + }, + &api.ListResult{ + Items: []interface{}{pvc1}, + TotalItems: 1, + }, + nil, + }, + { + "test StorageClass filter and allow snapshot", + "default", + &query.Query{ + Pagination: &query.Pagination{ + Limit: 10, + Offset: 0, + }, + SortBy: query.FieldName, + Ascending: false, + Filters: map[query.Field]query.Value{ + query.FieldNamespace: query.Value("default"), + query.Field(storageClassName): query.Value(*pvc2.Spec.StorageClassName), + }, + }, + &api.ListResult{ + Items: []interface{}{pvcGet2}, + TotalItems: 1, + }, + nil, + }, + { + "test pvc in use", + "default", + &query.Query{ + Pagination: &query.Pagination{ + Limit: 10, + Offset: 0, + }, + SortBy: query.FieldName, + Ascending: false, + Filters: map[query.Field]query.Value{ + query.FieldNamespace: query.Value("default"), + query.FieldName: query.Value(pvc3.Name), + }, + }, + &api.ListResult{ + Items: []interface{}{pvcGet3}, + 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 ( + pvc1 = &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pvc-1", + Namespace: "default", + }, + Status: corev1.PersistentVolumeClaimStatus{ + Phase: corev1.ClaimPending, + }, + } + pvc2 = &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pvc-2", + Namespace: "default", + Annotations: map[string]string{ + annotationStorageProvisioner: testStorageClassName, + }, + }, + Spec: corev1.PersistentVolumeClaimSpec{ + StorageClassName: &testStorageClassName, + }, + } + + pvcGet2 = &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pvc-2", + Namespace: "default", + Annotations: map[string]string{ + annotationInUse: "false", + annotationAllowSnapshot: "true", + annotationStorageProvisioner: testStorageClassName, + }, + }, + Spec: corev1.PersistentVolumeClaimSpec{ + StorageClassName: &testStorageClassName, + }, + } + + pvc3 = &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pvc-3", + Namespace: "default", + }, + } + + pvcGet3 = &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pvc-3", + Namespace: "default", + Annotations: map[string]string{ + annotationInUse: "true", + annotationAllowSnapshot: "false", + }, + }, + } + + pod1 = &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-1", + Namespace: "default", + }, + Spec: corev1.PodSpec{ + Volumes: []corev1.Volume{ + { + Name: "data", + VolumeSource: corev1.VolumeSource{ + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: pvc3.Name, + }, + }, + }, + }, + }, + } + + volumeSnapshotClass1 = &snapshot.VolumeSnapshotClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: "VolumeSnapshotClass-1", + Namespace: "default", + }, + Driver: testStorageClassName, + } + + persistentVolumeClaims = []interface{}{pvc1, pvc2, pvc3} + pods = []interface{}{pod1} + volumeSnapshotClasses = []interface{}{volumeSnapshotClass1} +) + +func prepare() v1alpha3.Interface { + client := fake.NewSimpleClientset() + informer := informers.NewSharedInformerFactory(client, 0) + snapshotClient := snapshotefakeclient.NewSimpleClientset() + snapshotInformers := snapshotinformers.NewSharedInformerFactory(snapshotClient, 0) + + for _, pvc := range persistentVolumeClaims { + _ = informer.Core().V1().PersistentVolumeClaims().Informer().GetIndexer().Add(pvc) + } + for _, pod := range pods { + _ = informer.Core().V1().Pods().Informer().GetIndexer().Add(pod) + } + for _, volumeSnapshotClass := range volumeSnapshotClasses { + _ = snapshotInformers.Snapshot().V1beta1().VolumeSnapshotClasses().Informer().GetIndexer().Add(volumeSnapshotClass) + } + + return New(informer, snapshotInformers) +} diff --git a/pkg/models/resources/v1alpha3/pod/pods.go b/pkg/models/resources/v1alpha3/pod/pods.go index bdfa845a391ddb51ddfcb6a459235c34ece59fd8..8af95c40cce1b09c982f8102873ab62a1023ecdc 100644 --- a/pkg/models/resources/v1alpha3/pod/pods.go +++ b/pkg/models/resources/v1alpha3/pod/pods.go @@ -27,6 +27,12 @@ import ( "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3" ) +const ( + filedNameName = "nodeName" + filedPVCName = "pvcName" + filedServiceName = "serviceName" +) + type podsGetter struct { informer informers.SharedInformerFactory } @@ -35,13 +41,13 @@ func New(sharedInformers informers.SharedInformerFactory) v1alpha3.Interface { return &podsGetter{informer: sharedInformers} } -func (d *podsGetter) Get(namespace, name string) (runtime.Object, error) { - return d.informer.Core().V1().Pods().Lister().Pods(namespace).Get(name) +func (p *podsGetter) Get(namespace, name string) (runtime.Object, error) { + return p.informer.Core().V1().Pods().Lister().Pods(namespace).Get(name) } -func (d *podsGetter) List(namespace string, query *query.Query) (*api.ListResult, error) { +func (p *podsGetter) List(namespace string, query *query.Query) (*api.ListResult, error) { - all, err := d.informer.Core().V1().Pods().Lister().Pods(namespace).List(query.Selector()) + all, err := p.informer.Core().V1().Pods().Lister().Pods(namespace).List(query.Selector()) if err != nil { return nil, err } @@ -51,10 +57,10 @@ func (d *podsGetter) List(namespace string, query *query.Query) (*api.ListResult result = append(result, app) } - return v1alpha3.DefaultList(result, query, d.compare, d.filter), nil + return v1alpha3.DefaultList(result, query, p.compare, p.filter), nil } -func (d *podsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool { +func (p *podsGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool { leftPod, ok := left.(*corev1.Pod) if !ok { @@ -69,30 +75,25 @@ func (d *podsGetter) compare(left runtime.Object, right runtime.Object, field qu return v1alpha3.DefaultObjectMetaCompare(leftPod.ObjectMeta, rightPod.ObjectMeta, field) } -func (d *podsGetter) filter(object runtime.Object, filter query.Filter) bool { +func (p *podsGetter) filter(object runtime.Object, filter query.Filter) bool { pod, ok := object.(*corev1.Pod) if !ok { return false } switch filter.Field { - case "nodeName": - if pod.Spec.NodeName != string(filter.Value) { - return false - } - case "pvcName": - if !d.podBindPVC(pod, string(filter.Value)) { - return false - } - case "serviceName": - if !d.podBelongToService(pod, string(filter.Value)) { - return false - } + case filedNameName: + return pod.Spec.NodeName == string(filter.Value) + case filedPVCName: + return p.podBindPVC(pod, string(filter.Value)) + case filedServiceName: + return p.podBelongToService(pod, string(filter.Value)) + default: + return v1alpha3.DefaultObjectMetaFilter(pod.ObjectMeta, filter) } - return v1alpha3.DefaultObjectMetaFilter(pod.ObjectMeta, filter) } -func (s *podsGetter) podBindPVC(item *corev1.Pod, pvcName string) bool { +func (p *podsGetter) podBindPVC(item *corev1.Pod, pvcName string) bool { for _, v := range item.Spec.Volumes { if v.VolumeSource.PersistentVolumeClaim != nil && v.VolumeSource.PersistentVolumeClaim.ClaimName == pvcName { @@ -102,8 +103,8 @@ func (s *podsGetter) podBindPVC(item *corev1.Pod, pvcName string) bool { return false } -func (s *podsGetter) podBelongToService(item *corev1.Pod, serviceName string) bool { - service, err := s.informer.Core().V1().Services().Lister().Services(item.Namespace).Get(serviceName) +func (p *podsGetter) podBelongToService(item *corev1.Pod, serviceName string) bool { + service, err := p.informer.Core().V1().Services().Lister().Services(item.Namespace).Get(serviceName) if err != nil { return false } diff --git a/pkg/models/resources/v1alpha3/pod/pods_test.go b/pkg/models/resources/v1alpha3/pod/pods_test.go index d5fb596520943d7aeb1da80c16dcb1d77433ab60..12d739a4eb67bb9ad4e8c9782fdd50cc58559537 100644 --- a/pkg/models/resources/v1alpha3/pod/pods_test.go +++ b/pkg/models/resources/v1alpha3/pod/pods_test.go @@ -33,11 +33,32 @@ func TestListPods(t *testing.T) { Filters: map[query.Field]query.Value{query.FieldNamespace: query.Value("default")}, }, &api.ListResult{ - Items: []interface{}{foo3, foo2, foo1}, + Items: []interface{}{foo4, foo3, foo2, foo1}, TotalItems: len(pods), }, nil, }, + { + "test pvcName filter", + "default", + &query.Query{ + Pagination: &query.Pagination{ + Limit: 10, + Offset: 0, + }, + SortBy: query.FieldName, + Ascending: false, + Filters: map[query.Field]query.Value{ + query.FieldNamespace: query.Value("default"), + filedPVCName: query.Value(foo4.Spec.Volumes[0].PersistentVolumeClaim.ClaimName), + }, + }, + &api.ListResult{ + Items: []interface{}{foo4}, + TotalItems: 1, + }, + nil, + }, } getter := prepare() @@ -75,7 +96,26 @@ var ( Namespace: "default", }, } - pods = []interface{}{foo1, foo2, foo3} + foo4 = &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo4", + Namespace: "default", + }, + Spec: corev1.PodSpec{ + Volumes: []corev1.Volume{ + { + Name: "data", + VolumeSource: corev1.VolumeSource{ + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: "pvc-1", + ReadOnly: false, + }, + }, + }, + }, + }, + } + pods = []interface{}{foo1, foo2, foo3, foo4} ) func prepare() v1alpha3.Interface { @@ -84,7 +124,7 @@ func prepare() v1alpha3.Interface { informer := informers.NewSharedInformerFactory(client, 0) for _, pod := range pods { - informer.Core().V1().Pods().Informer().GetIndexer().Add(pod) + _ = informer.Core().V1().Pods().Informer().GetIndexer().Add(pod) } return New(informer) diff --git a/pkg/models/resources/v1alpha3/resource/resource.go b/pkg/models/resources/v1alpha3/resource/resource.go index 07f51fb00c50881a84dda803f86f3c0f5ce47398..d195513abd85bfb2300694adbe90b0143fc88d6a 100644 --- a/pkg/models/resources/v1alpha3/resource/resource.go +++ b/pkg/models/resources/v1alpha3/resource/resource.go @@ -39,6 +39,7 @@ import ( "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/globalrole" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/namespace" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/networkpolicy" + "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/persistentvolumeclaim" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/pod" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/role" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/user" @@ -68,6 +69,7 @@ func NewResourceGetter(factory informers.InformerFactory) *ResourceGetter { getters[iamv1alpha2.SchemeGroupVersion.WithResource(iamv1alpha2.ResourcesPluralUser)] = user.New(factory.KubeSphereSharedInformerFactory()) getters[rbacv1.SchemeGroupVersion.WithResource("roles")] = role.New(factory.KubernetesSharedInformerFactory()) getters[rbacv1.SchemeGroupVersion.WithResource("clusterroles")] = clusterrole.New(factory.KubernetesSharedInformerFactory()) + getters[schema.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumeclaims"}] = persistentvolumeclaim.New(factory.KubernetesSharedInformerFactory(), factory.SnapshotSharedInformerFactory()) getters[snapshotv1beta1.SchemeGroupVersion.WithResource("volumesnapshots")] = volumesnapshot.New(factory.SnapshotSharedInformerFactory()) getters[schema.GroupVersionResource{Group: "cluster.kubesphere.io", Version: "v1alpha1", Resource: "clusters"}] = cluster.New(factory.KubeSphereSharedInformerFactory()) getters[schema.GroupVersionResource{Group: "apiextensions.k8s.io", Version: "v1", Resource: "customresourcedefinitions"}] = customresourcedefinition.New(factory.ApiExtensionSharedInformerFactory()) diff --git a/pkg/models/resources/v1alpha3/volumesnapshot/volumesnapshot.go b/pkg/models/resources/v1alpha3/volumesnapshot/volumesnapshot.go index a373ac1650b283a7f458cfd485956aca5f62c5d3..4e7ddc57d5dbf691be2599cc04d65f4a57446a6e 100644 --- a/pkg/models/resources/v1alpha3/volumesnapshot/volumesnapshot.go +++ b/pkg/models/resources/v1alpha3/volumesnapshot/volumesnapshot.go @@ -20,7 +20,6 @@ package volumesnapshot import ( "github.com/kubernetes-csi/external-snapshotter/v2/pkg/apis/volumesnapshot/v1beta1" "github.com/kubernetes-csi/external-snapshotter/v2/pkg/client/informers/externalversions" - "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "kubesphere.io/kubesphere/pkg/api" "kubesphere.io/kubesphere/pkg/apiserver/query" @@ -36,26 +35,26 @@ const ( ) type volumeSnapshotGetter struct { - informer externalversions.SharedInformerFactory + informers externalversions.SharedInformerFactory } func New(informer externalversions.SharedInformerFactory) v1alpha3.Interface { - return &volumeSnapshotGetter{informer: informer} + return &volumeSnapshotGetter{informers: informer} } func (v *volumeSnapshotGetter) Get(namespace, name string) (runtime.Object, error) { - return v.informer.Snapshot().V1beta1().VolumeSnapshots().Lister().VolumeSnapshots(namespace).Get(name) + return v.informers.Snapshot().V1beta1().VolumeSnapshots().Lister().VolumeSnapshots(namespace).Get(name) } func (v *volumeSnapshotGetter) List(namespace string, query *query.Query) (*api.ListResult, error) { - all, err := v.listVolumeSnapshots(namespace, query.Selector()) + all, err := v.informers.Snapshot().V1beta1().VolumeSnapshots().Lister().VolumeSnapshots(namespace).List(query.Selector()) if err != nil { return nil, err } var result []runtime.Object - for _, app := range all { - result = append(result, app) + for _, snapshot := range all { + result = append(result, snapshot) } return v1alpha3.DefaultList(result, query, v.compare, v.filter), nil @@ -93,10 +92,6 @@ func (v *volumeSnapshotGetter) filter(object runtime.Object, filter query.Filter } } -func (v *volumeSnapshotGetter) listVolumeSnapshots(namespace string, selector labels.Selector) (ret []*v1beta1.VolumeSnapshot, err error) { - return v.informer.Snapshot().V1beta1().VolumeSnapshots().Lister().VolumeSnapshots(namespace).List(selector) -} - func snapshotStatus(item *v1beta1.VolumeSnapshot) string { status := statusCreating if *item.Status.ReadyToUse {