remove capability CRDs and update controller

Signed-off-by: f10atin9 <f10atin9@kubesphere.io>
This commit is contained in:
f10atin9
2021-08-18 01:19:45 +08:00
parent ddc645838d
commit 574eb221ab
13 changed files with 165 additions and 1132 deletions

View File

@@ -96,10 +96,9 @@ func addControllers(
jobController := job.NewJobController(kubernetesInformer.Batch().V1().Jobs(), client.Kubernetes())
storageCapabilityController := capability.NewController(
client.KubeSphere().StorageV1alpha1().StorageClassCapabilities(),
kubesphereInformer.Storage().V1alpha1(),
client.Kubernetes().StorageV1().StorageClasses(),
kubernetesInformer.Storage().V1().StorageClasses(),
kubernetesInformer.Storage().V1beta1().CSIDrivers(),
capability.SnapshotSupported(client.Kubernetes().Discovery()),
client.Snapshot().SnapshotV1beta1().VolumeSnapshotClasses(),
informerFactory.SnapshotSharedInformerFactory().Snapshot().V1beta1().VolumeSnapshotClasses(),

View File

@@ -1,122 +0,0 @@
/*
Copyright 2020 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
"context"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
v1alpha1 "kubesphere.io/api/storage/v1alpha1"
)
// FakeProvisionerCapabilities implements ProvisionerCapabilityInterface
type FakeProvisionerCapabilities struct {
Fake *FakeStorageV1alpha1
}
var provisionercapabilitiesResource = schema.GroupVersionResource{Group: "storage.kubesphere.io", Version: "v1alpha1", Resource: "provisionercapabilities"}
var provisionercapabilitiesKind = schema.GroupVersionKind{Group: "storage.kubesphere.io", Version: "v1alpha1", Kind: "ProvisionerCapability"}
// Get takes name of the provisionerCapability, and returns the corresponding provisionerCapability object, and an error if there is any.
func (c *FakeProvisionerCapabilities) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ProvisionerCapability, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootGetAction(provisionercapabilitiesResource, name), &v1alpha1.ProvisionerCapability{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ProvisionerCapability), err
}
// List takes label and field selectors, and returns the list of ProvisionerCapabilities that match those selectors.
func (c *FakeProvisionerCapabilities) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ProvisionerCapabilityList, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootListAction(provisionercapabilitiesResource, provisionercapabilitiesKind, opts), &v1alpha1.ProvisionerCapabilityList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1alpha1.ProvisionerCapabilityList{ListMeta: obj.(*v1alpha1.ProvisionerCapabilityList).ListMeta}
for _, item := range obj.(*v1alpha1.ProvisionerCapabilityList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested provisionerCapabilities.
func (c *FakeProvisionerCapabilities) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewRootWatchAction(provisionercapabilitiesResource, opts))
}
// Create takes the representation of a provisionerCapability and creates it. Returns the server's representation of the provisionerCapability, and an error, if there is any.
func (c *FakeProvisionerCapabilities) Create(ctx context.Context, provisionerCapability *v1alpha1.ProvisionerCapability, opts v1.CreateOptions) (result *v1alpha1.ProvisionerCapability, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootCreateAction(provisionercapabilitiesResource, provisionerCapability), &v1alpha1.ProvisionerCapability{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ProvisionerCapability), err
}
// Update takes the representation of a provisionerCapability and updates it. Returns the server's representation of the provisionerCapability, and an error, if there is any.
func (c *FakeProvisionerCapabilities) Update(ctx context.Context, provisionerCapability *v1alpha1.ProvisionerCapability, opts v1.UpdateOptions) (result *v1alpha1.ProvisionerCapability, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootUpdateAction(provisionercapabilitiesResource, provisionerCapability), &v1alpha1.ProvisionerCapability{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ProvisionerCapability), err
}
// Delete takes name of the provisionerCapability and deletes it. Returns an error if one occurs.
func (c *FakeProvisionerCapabilities) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewRootDeleteAction(provisionercapabilitiesResource, name), &v1alpha1.ProvisionerCapability{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeProvisionerCapabilities) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
action := testing.NewRootDeleteCollectionAction(provisionercapabilitiesResource, listOpts)
_, err := c.Fake.Invokes(action, &v1alpha1.ProvisionerCapabilityList{})
return err
}
// Patch applies the patch and returns the patched provisionerCapability.
func (c *FakeProvisionerCapabilities) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ProvisionerCapability, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootPatchSubresourceAction(provisionercapabilitiesResource, name, pt, data, subresources...), &v1alpha1.ProvisionerCapability{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ProvisionerCapability), err
}

View File

@@ -21,21 +21,12 @@ package fake
import (
rest "k8s.io/client-go/rest"
testing "k8s.io/client-go/testing"
v1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/storage/v1alpha1"
)
type FakeStorageV1alpha1 struct {
*testing.Fake
}
func (c *FakeStorageV1alpha1) ProvisionerCapabilities() v1alpha1.ProvisionerCapabilityInterface {
return &FakeProvisionerCapabilities{c}
}
func (c *FakeStorageV1alpha1) StorageClassCapabilities() v1alpha1.StorageClassCapabilityInterface {
return &FakeStorageClassCapabilities{c}
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakeStorageV1alpha1) RESTClient() rest.Interface {

View File

@@ -1,122 +0,0 @@
/*
Copyright 2020 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
"context"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
v1alpha1 "kubesphere.io/api/storage/v1alpha1"
)
// FakeStorageClassCapabilities implements StorageClassCapabilityInterface
type FakeStorageClassCapabilities struct {
Fake *FakeStorageV1alpha1
}
var storageclasscapabilitiesResource = schema.GroupVersionResource{Group: "storage.kubesphere.io", Version: "v1alpha1", Resource: "storageclasscapabilities"}
var storageclasscapabilitiesKind = schema.GroupVersionKind{Group: "storage.kubesphere.io", Version: "v1alpha1", Kind: "StorageClassCapability"}
// Get takes name of the storageClassCapability, and returns the corresponding storageClassCapability object, and an error if there is any.
func (c *FakeStorageClassCapabilities) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.StorageClassCapability, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootGetAction(storageclasscapabilitiesResource, name), &v1alpha1.StorageClassCapability{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.StorageClassCapability), err
}
// List takes label and field selectors, and returns the list of StorageClassCapabilities that match those selectors.
func (c *FakeStorageClassCapabilities) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.StorageClassCapabilityList, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootListAction(storageclasscapabilitiesResource, storageclasscapabilitiesKind, opts), &v1alpha1.StorageClassCapabilityList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1alpha1.StorageClassCapabilityList{ListMeta: obj.(*v1alpha1.StorageClassCapabilityList).ListMeta}
for _, item := range obj.(*v1alpha1.StorageClassCapabilityList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested storageClassCapabilities.
func (c *FakeStorageClassCapabilities) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewRootWatchAction(storageclasscapabilitiesResource, opts))
}
// Create takes the representation of a storageClassCapability and creates it. Returns the server's representation of the storageClassCapability, and an error, if there is any.
func (c *FakeStorageClassCapabilities) Create(ctx context.Context, storageClassCapability *v1alpha1.StorageClassCapability, opts v1.CreateOptions) (result *v1alpha1.StorageClassCapability, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootCreateAction(storageclasscapabilitiesResource, storageClassCapability), &v1alpha1.StorageClassCapability{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.StorageClassCapability), err
}
// Update takes the representation of a storageClassCapability and updates it. Returns the server's representation of the storageClassCapability, and an error, if there is any.
func (c *FakeStorageClassCapabilities) Update(ctx context.Context, storageClassCapability *v1alpha1.StorageClassCapability, opts v1.UpdateOptions) (result *v1alpha1.StorageClassCapability, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootUpdateAction(storageclasscapabilitiesResource, storageClassCapability), &v1alpha1.StorageClassCapability{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.StorageClassCapability), err
}
// Delete takes name of the storageClassCapability and deletes it. Returns an error if one occurs.
func (c *FakeStorageClassCapabilities) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewRootDeleteAction(storageclasscapabilitiesResource, name), &v1alpha1.StorageClassCapability{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeStorageClassCapabilities) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
action := testing.NewRootDeleteCollectionAction(storageclasscapabilitiesResource, listOpts)
_, err := c.Fake.Invokes(action, &v1alpha1.StorageClassCapabilityList{})
return err
}
// Patch applies the patch and returns the patched storageClassCapability.
func (c *FakeStorageClassCapabilities) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.StorageClassCapability, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootPatchSubresourceAction(storageclasscapabilitiesResource, name, pt, data, subresources...), &v1alpha1.StorageClassCapability{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.StorageClassCapability), err
}

View File

@@ -1,168 +0,0 @@
/*
Copyright 2020 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
import (
"context"
"time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
v1alpha1 "kubesphere.io/api/storage/v1alpha1"
scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme"
)
// ProvisionerCapabilitiesGetter has a method to return a ProvisionerCapabilityInterface.
// A group's client should implement this interface.
type ProvisionerCapabilitiesGetter interface {
ProvisionerCapabilities() ProvisionerCapabilityInterface
}
// ProvisionerCapabilityInterface has methods to work with ProvisionerCapability resources.
type ProvisionerCapabilityInterface interface {
Create(ctx context.Context, provisionerCapability *v1alpha1.ProvisionerCapability, opts v1.CreateOptions) (*v1alpha1.ProvisionerCapability, error)
Update(ctx context.Context, provisionerCapability *v1alpha1.ProvisionerCapability, opts v1.UpdateOptions) (*v1alpha1.ProvisionerCapability, error)
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ProvisionerCapability, error)
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ProvisionerCapabilityList, error)
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ProvisionerCapability, err error)
ProvisionerCapabilityExpansion
}
// provisionerCapabilities implements ProvisionerCapabilityInterface
type provisionerCapabilities struct {
client rest.Interface
}
// newProvisionerCapabilities returns a ProvisionerCapabilities
func newProvisionerCapabilities(c *StorageV1alpha1Client) *provisionerCapabilities {
return &provisionerCapabilities{
client: c.RESTClient(),
}
}
// Get takes name of the provisionerCapability, and returns the corresponding provisionerCapability object, and an error if there is any.
func (c *provisionerCapabilities) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ProvisionerCapability, err error) {
result = &v1alpha1.ProvisionerCapability{}
err = c.client.Get().
Resource("provisionercapabilities").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do(ctx).
Into(result)
return
}
// List takes label and field selectors, and returns the list of ProvisionerCapabilities that match those selectors.
func (c *provisionerCapabilities) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ProvisionerCapabilityList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1alpha1.ProvisionerCapabilityList{}
err = c.client.Get().
Resource("provisionercapabilities").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do(ctx).
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested provisionerCapabilities.
func (c *provisionerCapabilities) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Resource("provisionercapabilities").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch(ctx)
}
// Create takes the representation of a provisionerCapability and creates it. Returns the server's representation of the provisionerCapability, and an error, if there is any.
func (c *provisionerCapabilities) Create(ctx context.Context, provisionerCapability *v1alpha1.ProvisionerCapability, opts v1.CreateOptions) (result *v1alpha1.ProvisionerCapability, err error) {
result = &v1alpha1.ProvisionerCapability{}
err = c.client.Post().
Resource("provisionercapabilities").
VersionedParams(&opts, scheme.ParameterCodec).
Body(provisionerCapability).
Do(ctx).
Into(result)
return
}
// Update takes the representation of a provisionerCapability and updates it. Returns the server's representation of the provisionerCapability, and an error, if there is any.
func (c *provisionerCapabilities) Update(ctx context.Context, provisionerCapability *v1alpha1.ProvisionerCapability, opts v1.UpdateOptions) (result *v1alpha1.ProvisionerCapability, err error) {
result = &v1alpha1.ProvisionerCapability{}
err = c.client.Put().
Resource("provisionercapabilities").
Name(provisionerCapability.Name).
VersionedParams(&opts, scheme.ParameterCodec).
Body(provisionerCapability).
Do(ctx).
Into(result)
return
}
// Delete takes name of the provisionerCapability and deletes it. Returns an error if one occurs.
func (c *provisionerCapabilities) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
return c.client.Delete().
Resource("provisionercapabilities").
Name(name).
Body(&opts).
Do(ctx).
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *provisionerCapabilities) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
var timeout time.Duration
if listOpts.TimeoutSeconds != nil {
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Resource("provisionercapabilities").
VersionedParams(&listOpts, scheme.ParameterCodec).
Timeout(timeout).
Body(&opts).
Do(ctx).
Error()
}
// Patch applies the patch and returns the patched provisionerCapability.
func (c *provisionerCapabilities) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ProvisionerCapability, err error) {
result = &v1alpha1.ProvisionerCapability{}
err = c.client.Patch(pt).
Resource("provisionercapabilities").
Name(name).
SubResource(subresources...).
VersionedParams(&opts, scheme.ParameterCodec).
Body(data).
Do(ctx).
Into(result)
return
}

View File

@@ -26,8 +26,6 @@ import (
type StorageV1alpha1Interface interface {
RESTClient() rest.Interface
ProvisionerCapabilitiesGetter
StorageClassCapabilitiesGetter
}
// StorageV1alpha1Client is used to interact with features provided by the storage.kubesphere.io group.
@@ -35,14 +33,6 @@ type StorageV1alpha1Client struct {
restClient rest.Interface
}
func (c *StorageV1alpha1Client) ProvisionerCapabilities() ProvisionerCapabilityInterface {
return newProvisionerCapabilities(c)
}
func (c *StorageV1alpha1Client) StorageClassCapabilities() StorageClassCapabilityInterface {
return newStorageClassCapabilities(c)
}
// NewForConfig creates a new StorageV1alpha1Client for the given config.
func NewForConfig(c *rest.Config) (*StorageV1alpha1Client, error) {
config := *c

View File

@@ -1,168 +0,0 @@
/*
Copyright 2020 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
import (
"context"
"time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
v1alpha1 "kubesphere.io/api/storage/v1alpha1"
scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme"
)
// StorageClassCapabilitiesGetter has a method to return a StorageClassCapabilityInterface.
// A group's client should implement this interface.
type StorageClassCapabilitiesGetter interface {
StorageClassCapabilities() StorageClassCapabilityInterface
}
// StorageClassCapabilityInterface has methods to work with StorageClassCapability resources.
type StorageClassCapabilityInterface interface {
Create(ctx context.Context, storageClassCapability *v1alpha1.StorageClassCapability, opts v1.CreateOptions) (*v1alpha1.StorageClassCapability, error)
Update(ctx context.Context, storageClassCapability *v1alpha1.StorageClassCapability, opts v1.UpdateOptions) (*v1alpha1.StorageClassCapability, error)
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.StorageClassCapability, error)
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.StorageClassCapabilityList, error)
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.StorageClassCapability, err error)
StorageClassCapabilityExpansion
}
// storageClassCapabilities implements StorageClassCapabilityInterface
type storageClassCapabilities struct {
client rest.Interface
}
// newStorageClassCapabilities returns a StorageClassCapabilities
func newStorageClassCapabilities(c *StorageV1alpha1Client) *storageClassCapabilities {
return &storageClassCapabilities{
client: c.RESTClient(),
}
}
// Get takes name of the storageClassCapability, and returns the corresponding storageClassCapability object, and an error if there is any.
func (c *storageClassCapabilities) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.StorageClassCapability, err error) {
result = &v1alpha1.StorageClassCapability{}
err = c.client.Get().
Resource("storageclasscapabilities").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do(ctx).
Into(result)
return
}
// List takes label and field selectors, and returns the list of StorageClassCapabilities that match those selectors.
func (c *storageClassCapabilities) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.StorageClassCapabilityList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1alpha1.StorageClassCapabilityList{}
err = c.client.Get().
Resource("storageclasscapabilities").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do(ctx).
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested storageClassCapabilities.
func (c *storageClassCapabilities) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Resource("storageclasscapabilities").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch(ctx)
}
// Create takes the representation of a storageClassCapability and creates it. Returns the server's representation of the storageClassCapability, and an error, if there is any.
func (c *storageClassCapabilities) Create(ctx context.Context, storageClassCapability *v1alpha1.StorageClassCapability, opts v1.CreateOptions) (result *v1alpha1.StorageClassCapability, err error) {
result = &v1alpha1.StorageClassCapability{}
err = c.client.Post().
Resource("storageclasscapabilities").
VersionedParams(&opts, scheme.ParameterCodec).
Body(storageClassCapability).
Do(ctx).
Into(result)
return
}
// Update takes the representation of a storageClassCapability and updates it. Returns the server's representation of the storageClassCapability, and an error, if there is any.
func (c *storageClassCapabilities) Update(ctx context.Context, storageClassCapability *v1alpha1.StorageClassCapability, opts v1.UpdateOptions) (result *v1alpha1.StorageClassCapability, err error) {
result = &v1alpha1.StorageClassCapability{}
err = c.client.Put().
Resource("storageclasscapabilities").
Name(storageClassCapability.Name).
VersionedParams(&opts, scheme.ParameterCodec).
Body(storageClassCapability).
Do(ctx).
Into(result)
return
}
// Delete takes name of the storageClassCapability and deletes it. Returns an error if one occurs.
func (c *storageClassCapabilities) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
return c.client.Delete().
Resource("storageclasscapabilities").
Name(name).
Body(&opts).
Do(ctx).
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *storageClassCapabilities) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
var timeout time.Duration
if listOpts.TimeoutSeconds != nil {
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Resource("storageclasscapabilities").
VersionedParams(&listOpts, scheme.ParameterCodec).
Timeout(timeout).
Body(&opts).
Do(ctx).
Error()
}
// Patch applies the patch and returns the patched storageClassCapability.
func (c *storageClassCapabilities) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.StorageClassCapability, err error) {
result = &v1alpha1.StorageClassCapability{}
err = c.client.Patch(pt).
Resource("storageclasscapabilities").
Name(name).
SubResource(subresources...).
VersionedParams(&opts, scheme.ParameterCodec).
Body(data).
Do(ctx).
Into(result)
return
}

View File

@@ -33,7 +33,6 @@ import (
v2beta1 "kubesphere.io/api/notification/v2beta1"
quotav1alpha2 "kubesphere.io/api/quota/v1alpha2"
servicemeshv1alpha2 "kubesphere.io/api/servicemesh/v1alpha2"
storagev1alpha1 "kubesphere.io/api/storage/v1alpha1"
tenantv1alpha1 "kubesphere.io/api/tenant/v1alpha1"
tenantv1alpha2 "kubesphere.io/api/tenant/v1alpha2"
v1beta1 "kubesphere.io/api/types/v1beta1"
@@ -149,12 +148,6 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
case servicemeshv1alpha2.SchemeGroupVersion.WithResource("strategies"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Servicemesh().V1alpha2().Strategies().Informer()}, nil
// Group=storage.kubesphere.io, Version=v1alpha1
case storagev1alpha1.SchemeGroupVersion.WithResource("provisionercapabilities"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Storage().V1alpha1().ProvisionerCapabilities().Informer()}, nil
case storagev1alpha1.SchemeGroupVersion.WithResource("storageclasscapabilities"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Storage().V1alpha1().StorageClassCapabilities().Informer()}, nil
// Group=tenant.kubesphere.io, Version=v1alpha1
case tenantv1alpha1.SchemeGroupVersion.WithResource("workspaces"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Tenant().V1alpha1().Workspaces().Informer()}, nil

View File

@@ -24,10 +24,6 @@ import (
// Interface provides access to all the informers in this group version.
type Interface interface {
// ProvisionerCapabilities returns a ProvisionerCapabilityInformer.
ProvisionerCapabilities() ProvisionerCapabilityInformer
// StorageClassCapabilities returns a StorageClassCapabilityInformer.
StorageClassCapabilities() StorageClassCapabilityInformer
}
type version struct {
@@ -40,13 +36,3 @@ type version struct {
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// ProvisionerCapabilities returns a ProvisionerCapabilityInformer.
func (v *version) ProvisionerCapabilities() ProvisionerCapabilityInformer {
return &provisionerCapabilityInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
}
// StorageClassCapabilities returns a StorageClassCapabilityInformer.
func (v *version) StorageClassCapabilities() StorageClassCapabilityInformer {
return &storageClassCapabilityInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
}

View File

@@ -1,89 +0,0 @@
/*
Copyright 2020 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha1
import (
"context"
time "time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
storagev1alpha1 "kubesphere.io/api/storage/v1alpha1"
versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces"
v1alpha1 "kubesphere.io/kubesphere/pkg/client/listers/storage/v1alpha1"
)
// ProvisionerCapabilityInformer provides access to a shared informer and lister for
// ProvisionerCapabilities.
type ProvisionerCapabilityInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1alpha1.ProvisionerCapabilityLister
}
type provisionerCapabilityInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// NewProvisionerCapabilityInformer constructs a new informer for ProvisionerCapability type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewProvisionerCapabilityInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredProvisionerCapabilityInformer(client, resyncPeriod, indexers, nil)
}
// NewFilteredProvisionerCapabilityInformer constructs a new informer for ProvisionerCapability type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredProvisionerCapabilityInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.StorageV1alpha1().ProvisionerCapabilities().List(context.TODO(), options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.StorageV1alpha1().ProvisionerCapabilities().Watch(context.TODO(), options)
},
},
&storagev1alpha1.ProvisionerCapability{},
resyncPeriod,
indexers,
)
}
func (f *provisionerCapabilityInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredProvisionerCapabilityInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *provisionerCapabilityInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&storagev1alpha1.ProvisionerCapability{}, f.defaultInformer)
}
func (f *provisionerCapabilityInformer) Lister() v1alpha1.ProvisionerCapabilityLister {
return v1alpha1.NewProvisionerCapabilityLister(f.Informer().GetIndexer())
}

View File

@@ -1,89 +0,0 @@
/*
Copyright 2020 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha1
import (
"context"
time "time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
storagev1alpha1 "kubesphere.io/api/storage/v1alpha1"
versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces"
v1alpha1 "kubesphere.io/kubesphere/pkg/client/listers/storage/v1alpha1"
)
// StorageClassCapabilityInformer provides access to a shared informer and lister for
// StorageClassCapabilities.
type StorageClassCapabilityInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1alpha1.StorageClassCapabilityLister
}
type storageClassCapabilityInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// NewStorageClassCapabilityInformer constructs a new informer for StorageClassCapability type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewStorageClassCapabilityInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredStorageClassCapabilityInformer(client, resyncPeriod, indexers, nil)
}
// NewFilteredStorageClassCapabilityInformer constructs a new informer for StorageClassCapability type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredStorageClassCapabilityInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.StorageV1alpha1().StorageClassCapabilities().List(context.TODO(), options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.StorageV1alpha1().StorageClassCapabilities().Watch(context.TODO(), options)
},
},
&storagev1alpha1.StorageClassCapability{},
resyncPeriod,
indexers,
)
}
func (f *storageClassCapabilityInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredStorageClassCapabilityInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *storageClassCapabilityInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&storagev1alpha1.StorageClassCapability{}, f.defaultInformer)
}
func (f *storageClassCapabilityInformer) Lister() v1alpha1.StorageClassCapabilityLister {
return v1alpha1.NewStorageClassCapabilityLister(f.Informer().GetIndexer())
}

View File

@@ -21,18 +21,18 @@ package capability
import (
"context"
"fmt"
"reflect"
"strconv"
"strings"
"time"
snapinformers "github.com/kubernetes-csi/external-snapshotter/client/v3/informers/externalversions/volumesnapshot/v1beta1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/util/version"
"k8s.io/client-go/discovery"
storageinformersv1beta1 "k8s.io/client-go/informers/storage/v1beta1"
storagelistersv1beta1 "k8s.io/client-go/listers/storage/v1beta1"
snapshotv1beta1 "github.com/kubernetes-csi/external-snapshotter/client/v3/apis/volumesnapshot/v1beta1"
snapshotclient "github.com/kubernetes-csi/external-snapshotter/client/v3/clientset/versioned/typed/volumesnapshot/v1beta1"
snapinformers "github.com/kubernetes-csi/external-snapshotter/client/v3/informers/externalversions/volumesnapshot/v1beta1"
snapshotlisters "github.com/kubernetes-csi/external-snapshotter/client/v3/listers/volumesnapshot/v1beta1"
storagev1 "k8s.io/api/storage/v1"
"k8s.io/apimachinery/pkg/api/errors"
@@ -47,46 +47,38 @@ import (
"k8s.io/client-go/util/workqueue"
"k8s.io/klog"
ksstorage "kubesphere.io/api/storage/v1alpha1"
crdscheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme"
ksstorageclient "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/storage/v1alpha1"
ksstorageinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/storage/v1alpha1"
ksstoragelisters "kubesphere.io/kubesphere/pkg/client/listers/storage/v1alpha1"
)
const (
minSnapshotSupportedVersion = "v1.17.0"
annotationSupportSnapshot = "storageclass.kubesphere.io/support-snapshot"
annotationSupportSnapshot = "storageclass.kubesphere.io/allow-snapshot"
annotationSupportClone = "storageclass.kubesphere.io/allow-clone"
)
type StorageCapabilityController struct {
storageClassCapabilityClient ksstorageclient.StorageClassCapabilityInterface
storageClassCapabilityLister ksstoragelisters.StorageClassCapabilityLister
storageClassCapabilitySynced cache.InformerSynced
provisionerCapabilityLister ksstoragelisters.ProvisionerCapabilityLister
provisionerCapabilitySynced cache.InformerSynced
storageClassClient storageclient.StorageClassInterface
storageClassLister storagelistersv1.StorageClassLister
storageClassSynced cache.InformerSynced
csiDriverLister storagelistersv1beta1.CSIDriverLister
csiDriverSynced cache.InformerSynced
snapshotSupported bool
snapshotClassClient snapshotclient.VolumeSnapshotClassInterface
snapshotClassLister snapshotlisters.VolumeSnapshotClassLister
snapshotClassSynced cache.InformerSynced
workQueue workqueue.RateLimitingInterface
workQueue workqueue.RateLimitingInterface
csiWorkQueue workqueue.RateLimitingInterface
}
// This controller is responsible to watch StorageClass/ProvisionerCapability.
// And then update StorageClassCapability CRD resource object to the newest status.
func NewController(
storageClassCapabilityClient ksstorageclient.StorageClassCapabilityInterface,
ksStorageInformer ksstorageinformers.Interface,
storageClassClient storageclient.StorageClassInterface,
storageClassInformer storageinformersv1.StorageClassInformer,
csiDriverInformer storageinformersv1beta1.CSIDriverInformer,
snapshotSupported bool,
snapshotClassClient snapshotclient.VolumeSnapshotClassInterface,
snapshotClassInformer snapinformers.VolumeSnapshotClassInformer,
@@ -95,16 +87,14 @@ func NewController(
utilruntime.Must(crdscheme.AddToScheme(scheme.Scheme))
controller := &StorageCapabilityController{
storageClassCapabilityClient: storageClassCapabilityClient,
storageClassCapabilityLister: ksStorageInformer.StorageClassCapabilities().Lister(),
storageClassCapabilitySynced: ksStorageInformer.StorageClassCapabilities().Informer().HasSynced,
provisionerCapabilityLister: ksStorageInformer.ProvisionerCapabilities().Lister(),
provisionerCapabilitySynced: ksStorageInformer.ProvisionerCapabilities().Informer().HasSynced,
storageClassClient: storageClassClient,
storageClassLister: storageClassInformer.Lister(),
storageClassSynced: storageClassInformer.Informer().HasSynced,
snapshotSupported: snapshotSupported,
workQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "StorageClasses"),
storageClassClient: storageClassClient,
storageClassLister: storageClassInformer.Lister(),
storageClassSynced: storageClassInformer.Informer().HasSynced,
csiDriverLister: csiDriverInformer.Lister(),
csiDriverSynced: csiDriverInformer.Informer().HasSynced,
snapshotSupported: snapshotSupported,
workQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "StorageClasses"),
csiWorkQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "csiDriver"),
}
if snapshotSupported {
@@ -126,24 +116,10 @@ func NewController(
DeleteFunc: controller.enqueueStorageClass,
})
// ProvisionerCapability acts as a value source of its relevant StorageClassCapabilities
// so when a PC is created/updated, the corresponding SCCs should be created(if not exists)/updated
// we achieve this by simply enqueueing the StorageClasses of the same provisioner
// but don't overdo by cascade deleting the SCCs when a PC is deleted
// since the role of PCs is more like a template rather than owner to SCCs
// This is a backward compatible fix to remove the useless auto detection of SCCs
// in the future, we will only keep ProvisionerCapability and remove the StorageClassCapability CRD entirely
ksStorageInformer.ProvisionerCapabilities().Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: controller.handleProvisionerCapability,
UpdateFunc: func(oldObj, newObj interface{}) {
newPC := newObj.(*ksstorage.ProvisionerCapability)
oldPC := oldObj.(*ksstorage.ProvisionerCapability)
if newPC.ResourceVersion == oldPC.ResourceVersion {
return
}
controller.handleProvisionerCapability(newObj)
},
csiDriverInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: controller.enqueueStorageClassByCSI,
UpdateFunc: nil,
DeleteFunc: controller.enqueueStorageClassByCSI,
})
return controller
@@ -160,13 +136,8 @@ func (c *StorageCapabilityController) Run(threadCnt int, stopCh <-chan struct{})
// Wait for the caches to be synced before starting workers
klog.Info("Waiting for informer caches to sync")
cacheSyncs := []cache.InformerSynced{
c.storageClassCapabilitySynced,
c.provisionerCapabilitySynced,
c.storageClassSynced,
}
if c.snapshotAllowed() {
cacheSyncs = append(cacheSyncs, c.snapshotClassSynced)
c.csiDriverSynced,
}
if ok := cache.WaitForCacheSync(stopCh, cacheSyncs...); !ok {
@@ -182,21 +153,6 @@ func (c *StorageCapabilityController) Run(threadCnt int, stopCh <-chan struct{})
return nil
}
func (c *StorageCapabilityController) handleProvisionerCapability(obj interface{}) {
provisionerCapability := obj.(*ksstorage.ProvisionerCapability)
storageClasses, err := c.storageClassLister.List(labels.Everything())
if err != nil {
klog.Error("list StorageClass error when handle provisionerCapability", err)
return
}
for _, storageClass := range storageClasses {
if getProvisionerCapabilityName(storageClass.Provisioner) == provisionerCapability.Name {
klog.V(4).Infof("enqueue StorageClass %s while handling provisionerCapability", storageClass.Name)
c.enqueueStorageClass(storageClass)
}
}
}
func (c *StorageCapabilityController) enqueueStorageClass(obj interface{}) {
var key string
var err error
@@ -207,6 +163,27 @@ func (c *StorageCapabilityController) enqueueStorageClass(obj interface{}) {
c.workQueue.Add(key)
}
func (c *StorageCapabilityController) enqueueStorageClassByCSI(csi interface{}) {
var objs []*storagev1.StorageClass
var key string
var err error
if key, err = cache.MetaNamespaceKeyFunc(csi); err != nil {
utilruntime.HandleError(err)
return
}
objs, err = c.storageClassLister.List(labels.NewSelector())
if err != nil {
utilruntime.HandleError(err)
return
}
for _, obj := range objs {
if obj.Provisioner == key {
c.workQueue.Add(obj.Name)
}
}
return
}
func (c *StorageCapabilityController) runWorker() {
for c.processNextWorkItem() {
}
@@ -257,40 +234,20 @@ func (c *StorageCapabilityController) syncHandler(key string) error {
storageClass, err := c.storageClassLister.Get(name)
if err != nil {
// StorageClass has been deleted, delete StorageClassCapability and VolumeSnapshotClass
if errors.IsNotFound(err) {
if c.snapshotAllowed() {
err = c.deleteSnapshotClass(name)
if err != nil {
return err
}
if errors.IsNotFound(err) && c.snapshotAllowed() {
err = c.deleteSnapshotClass(name)
if err != nil {
return err
}
return c.deleteStorageCapability(name)
}
return err
}
// Get capability spec
capabilitySpec, err := c.getCapabilitySpec(storageClass)
if err != nil {
return err
}
// The corresponding ProvisionerCapability Object does not exist
if capabilitySpec == nil {
klog.Infof("Can't get StorageClass %s's capability", name)
err = c.updateStorageClassSnapshotSupported(storageClass, false)
if err != nil {
return err
}
// Don't delete the already created SCC
// as it might be created manually by user
return nil
}
klog.Infof("StorageClass %s has capability %v", name, capabilitySpec)
//Cloning and volumeSnapshot support only available for CSI drivers.
withCapability := c.supportCapability(storageClass)
// Handle VolumeSnapshotClass with same name of StorageClass
// annotate "support-snapshot" of StorageClass
withSnapshotCapability := false
if c.snapshotAllowed() && capabilitySpec.Features.Snapshot.Create {
if c.snapshotAllowed() && withCapability {
_, err = c.snapshotClassLister.Get(name)
if err != nil {
// If VolumeSnapshotClass not exist, create it
@@ -306,63 +263,71 @@ func (c *StorageCapabilityController) syncHandler(key string) error {
}
}
}
withSnapshotCapability = true
}
err = c.updateStorageClassSnapshotSupported(storageClass, withSnapshotCapability)
if err != nil {
return err
}
// Handle StorageClassCapability with the same name of StorageClass
storageClassCapabilityExist, err := c.storageClassCapabilityLister.Get(storageClass.Name)
err = c.addStorageClassSnapshotAnnotation(storageClass, withCapability)
if err != nil {
if errors.IsNotFound(err) {
// If StorageClassCapability doesn't exist, create it
storageClassCapabilityCreate := &ksstorage.StorageClassCapability{ObjectMeta: metav1.ObjectMeta{Name: storageClass.Name}}
storageClassCapabilityCreate.Spec = *capabilitySpec
klog.Info("Create StorageClassCapability: ", storageClassCapabilityCreate)
_, err = c.storageClassCapabilityClient.Create(context.Background(), storageClassCapabilityCreate, metav1.CreateOptions{})
return err
}
return err
}
// If StorageClassCapability exist, update it.
storageClassCapabilityUpdate := storageClassCapabilityExist.DeepCopy()
storageClassCapabilityUpdate.Spec = *capabilitySpec
if !reflect.DeepEqual(storageClassCapabilityExist, storageClassCapabilityUpdate) {
klog.Info("Update StorageClassCapability: ", storageClassCapabilityUpdate)
_, err = c.storageClassCapabilityClient.Update(context.Background(), storageClassCapabilityUpdate, metav1.UpdateOptions{})
err = c.addCloneVolumeAnnotation(storageClass, withCapability)
if err != nil {
return nil
}
_, err = c.storageClassClient.Update(context.Background(), storageClass, metav1.UpdateOptions{})
if err != nil {
return err
}
return nil
}
func (c *StorageCapabilityController) updateStorageClassSnapshotSupported(storageClass *storagev1.StorageClass, snapshotSupported bool) error {
if storageClass.Annotations == nil {
storageClass.Annotations = make(map[string]string)
func (c *StorageCapabilityController) supportCapability(storageClass *storagev1.StorageClass) bool {
driver := storageClass.Provisioner
if driver != "" {
if _, err := c.csiDriverLister.Get(driver); err != nil {
return false
}
return true
}
snapshotSupportedAnnotated, err := strconv.ParseBool(storageClass.Annotations[annotationSupportSnapshot])
// err != nil means annotationSupportSnapshot is not illegal, include empty
if err != nil || snapshotSupported != snapshotSupportedAnnotated {
storageClass.Annotations[annotationSupportSnapshot] = strconv.FormatBool(snapshotSupported)
_, err = c.storageClassClient.Update(context.Background(), storageClass, metav1.UpdateOptions{})
return false
}
func (c *StorageCapabilityController) addStorageClassSnapshotAnnotation(storageClass *storagev1.StorageClass, snapshotSupported bool) error {
if snapshotSupported || !c.snapshotSupported {
if storageClass.Annotations == nil {
storageClass.Annotations = make(map[string]string)
}
_, err := strconv.ParseBool(storageClass.Annotations[annotationSupportSnapshot])
// err != nil means annotationSupportSnapshot is not illegal, include empty
if err != nil {
return err
storageClass.Annotations[annotationSupportSnapshot] = strconv.FormatBool(c.snapshotSupported)
}
} else {
if storageClass.Annotations != nil && c.snapshotSupported {
if _, ok := storageClass.Annotations[annotationSupportSnapshot]; ok {
delete(storageClass.Annotations, annotationSupportSnapshot)
}
}
}
return nil
}
func (c *StorageCapabilityController) deleteStorageCapability(name string) error {
_, err := c.storageClassCapabilityLister.Get(name)
if err != nil {
if errors.IsNotFound(err) {
return nil
func (c *StorageCapabilityController) addCloneVolumeAnnotation(storageClass *storagev1.StorageClass, cloneSupported bool) error {
if cloneSupported {
if storageClass.Annotations == nil {
storageClass.Annotations = make(map[string]string)
}
_, err := strconv.ParseBool(storageClass.Annotations[annotationSupportClone])
if err != nil {
storageClass.Annotations[annotationSupportClone] = strconv.FormatBool(cloneSupported)
}
} else {
if storageClass.Annotations != nil {
if _, ok := storageClass.Annotations[annotationSupportClone]; ok {
delete(storageClass.Annotations, annotationSupportClone)
}
}
return err
}
klog.Infof("Delete StorageClassCapability %s", name)
return c.storageClassCapabilityClient.Delete(context.Background(), name, metav1.DeleteOptions{})
return nil
}
func (c *StorageCapabilityController) deleteSnapshotClass(name string) error {
@@ -380,42 +345,6 @@ func (c *StorageCapabilityController) deleteSnapshotClass(name string) error {
return c.snapshotClassClient.Delete(context.Background(), name, metav1.DeleteOptions{})
}
func (c *StorageCapabilityController) capabilityFromProvisioner(provisioner string) (*ksstorage.StorageClassCapabilitySpec, error) {
provisionerCapability, err := c.provisionerCapabilityLister.Get(getProvisionerCapabilityName(provisioner))
if err != nil {
if errors.IsNotFound(err) {
return nil, nil
}
return nil, err
}
klog.V(4).Infof("get provisioner capability:%s %s", provisioner, provisionerCapability.Name)
capabilitySpec := &ksstorage.StorageClassCapabilitySpec{
Features: provisionerCapability.Spec.Features,
}
return capabilitySpec, nil
}
func (c *StorageCapabilityController) getCapabilitySpec(storageClass *storagev1.StorageClass) (*ksstorage.StorageClassCapabilitySpec, error) {
// get from provisioner capability first
klog.V(4).Info("get cap ", storageClass.Provisioner)
capabilitySpec, err := c.capabilityFromProvisioner(storageClass.Provisioner)
if err != nil {
return nil, err
}
if capabilitySpec != nil {
capabilitySpec.Provisioner = storageClass.Provisioner
if storageClass.AllowVolumeExpansion == nil || !*storageClass.AllowVolumeExpansion {
capabilitySpec.Features.Volume.Expand = ksstorage.ExpandModeUnknown
}
if !c.snapshotSupported {
capabilitySpec.Features.Snapshot.Create = false
capabilitySpec.Features.Snapshot.List = false
}
}
return capabilitySpec, nil
}
func (c *StorageCapabilityController) snapshotAllowed() bool {
return c.snapshotSupported && c.snapshotClassClient != nil && c.snapshotClassLister != nil && c.snapshotClassSynced != nil
}
@@ -432,7 +361,3 @@ func SnapshotSupported(discoveryInterface discovery.DiscoveryInterface) bool {
}
return ver.AtLeast(minVer)
}
func getProvisionerCapabilityName(provisioner string) string {
return strings.NewReplacer(".", "-", "/", "-").Replace(provisioner)
}

View File

@@ -20,6 +20,7 @@ package capability
import (
"github.com/google/go-cmp/cmp"
"k8s.io/api/storage/v1beta1"
"reflect"
"testing"
@@ -38,8 +39,6 @@ import (
core "k8s.io/client-go/testing"
"k8s.io/client-go/tools/cache"
ksv1alpha1 "kubesphere.io/api/storage/v1alpha1"
ksfake "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
)
@@ -60,10 +59,9 @@ type fixture struct {
snapshotClassObjects []runtime.Object
capabilityObjects []runtime.Object // include StorageClassCapability and ProvisionerCapability
// Objects to put in the store.
storageClassLister []*storagev1.StorageClass
snapshotClassLister []*snapbeta1.VolumeSnapshotClass
storageClassCapabilityLister []*ksv1alpha1.StorageClassCapability
provisionerCapabilityLister []*ksv1alpha1.ProvisionerCapability
storageClassLister []*storagev1.StorageClass
snapshotClassLister []*snapbeta1.VolumeSnapshotClass
csiDriverLister []*v1beta1.CSIDriver
// Actions expected to happen on the client.
actions []core.Action
}
@@ -89,10 +87,9 @@ func (f *fixture) newController() (*StorageCapabilityController,
snapshotInformers := snapinformers.NewSharedInformerFactory(f.snapshotClassClient, noReSyncPeriodFunc())
c := NewController(
f.ksClient.StorageV1alpha1().StorageClassCapabilities(),
ksInformers.Storage().V1alpha1(),
f.k8sClient.StorageV1().StorageClasses(),
k8sInformers.Storage().V1().StorageClasses(),
k8sInformers.Storage().V1beta1().CSIDrivers(),
f.snapshotSupported,
f.snapshotClassClient.SnapshotV1beta1().VolumeSnapshotClasses(),
snapshotInformers.Snapshot().V1beta1().VolumeSnapshotClasses(),
@@ -104,11 +101,8 @@ func (f *fixture) newController() (*StorageCapabilityController,
for _, snapshotClass := range f.snapshotClassLister {
_ = snapshotInformers.Snapshot().V1beta1().VolumeSnapshotClasses().Informer().GetIndexer().Add(snapshotClass)
}
for _, storageClassCapability := range f.storageClassCapabilityLister {
_ = ksInformers.Storage().V1alpha1().StorageClassCapabilities().Informer().GetIndexer().Add(storageClassCapability)
}
for _, provisionerCapability := range f.provisionerCapabilityLister {
_ = ksInformers.Storage().V1alpha1().ProvisionerCapabilities().Informer().GetIndexer().Add(provisionerCapability)
for _, csiDriver := range f.csiDriverLister {
_ = k8sInformers.Storage().V1beta1().CSIDrivers().Informer().GetIndexer().Add(csiDriver)
}
return c, k8sInformers, ksInformers, snapshotInformers
@@ -151,21 +145,6 @@ func (f *fixture) run(scName string) {
f.runController(scName, true, false)
}
func (f *fixture) expectCreateStorageClassCapabilitiesAction(storageClassCapability *ksv1alpha1.StorageClassCapability) {
f.actions = append(f.actions, core.NewCreateAction(
schema.GroupVersionResource{Resource: "storageclasscapabilities"}, storageClassCapability.Namespace, storageClassCapability))
}
func (f *fixture) expectUpdateStorageClassCapabilitiesAction(storageClassCapability *ksv1alpha1.StorageClassCapability) {
f.actions = append(f.actions, core.NewUpdateAction(
schema.GroupVersionResource{Resource: "storageclasscapabilities"}, storageClassCapability.Namespace, storageClassCapability))
}
func (f *fixture) expectDeleteStorageClassCapabilitiesAction(storageClassCapability *ksv1alpha1.StorageClassCapability) {
f.actions = append(f.actions, core.NewDeleteAction(
schema.GroupVersionResource{Resource: "storageclasscapabilities"}, storageClassCapability.Namespace, storageClassCapability.Name))
}
func (f *fixture) expectUpdateStorageClassAction(storageClass *storagev1.StorageClass) {
f.actions = append(f.actions, core.NewUpdateAction(
schema.GroupVersionResource{Resource: "storageclasses"}, storageClass.Namespace, storageClass))
@@ -253,42 +232,14 @@ func newStorageClass(name string, provisioner string) *storagev1.StorageClass {
}
}
func newStorageClassCapabilitySpec() *ksv1alpha1.StorageClassCapabilitySpec {
return &ksv1alpha1.StorageClassCapabilitySpec{
Features: ksv1alpha1.CapabilityFeatures{
Topology: false,
Volume: ksv1alpha1.VolumeFeature{
Create: true,
Attach: false,
List: false,
Clone: true,
Stats: true,
Expand: ksv1alpha1.ExpandModeOffline,
},
Snapshot: ksv1alpha1.SnapshotFeature{
Create: true,
List: false,
},
func newCSIDriver(name string) *v1beta1.CSIDriver {
return &v1beta1.CSIDriver{
ObjectMeta: v1.ObjectMeta{
Name: name,
},
}
}
func newStorageClassCapability(storageClass *storagev1.StorageClass) *ksv1alpha1.StorageClassCapability {
storageClassCapability := &ksv1alpha1.StorageClassCapability{}
storageClassCapability.Name = storageClass.Name
storageClassCapability.Spec = *newStorageClassCapabilitySpec()
storageClassCapability.Spec.Provisioner = storageClass.Provisioner
return storageClassCapability
}
func newProvisionerCapability(storageClass *storagev1.StorageClass) *ksv1alpha1.ProvisionerCapability {
provisionerCapability := &ksv1alpha1.ProvisionerCapability{}
provisionerCapability.Name = getProvisionerCapabilityName(storageClass.Provisioner)
provisionerCapability.Spec.PluginInfo.Name = storageClass.Provisioner
provisionerCapability.Spec.Features = newStorageClassCapabilitySpec().Features
return provisionerCapability
}
func newSnapshotClass(storageClass *storagev1.StorageClass) *snapbeta1.VolumeSnapshotClass {
return &snapbeta1.VolumeSnapshotClass{
ObjectMeta: v1.ObjectMeta{
@@ -312,88 +263,17 @@ func TestCreateStorageClass(t *testing.T) {
fixture := newFixture(t, true)
storageClass := newStorageClass("csi-example", "csi.example.com")
storageClassUpdate := storageClass.DeepCopy()
storageClassUpdate.Annotations = map[string]string{annotationSupportSnapshot: "true"}
provisionerCapability := newProvisionerCapability(storageClass)
storageClassUpdate.Annotations = map[string]string{annotationSupportSnapshot: "true", annotationSupportClone: "true"}
snapshotClass := newSnapshotClass(storageClass)
storageClassCapability := newStorageClassCapability(storageClass)
csiDriver := newCSIDriver("csi.example.com")
// Objects exist
fixture.storageObjects = append(fixture.storageObjects, storageClass)
fixture.storageClassLister = append(fixture.storageClassLister, storageClass)
fixture.capabilityObjects = append(fixture.capabilityObjects, provisionerCapability)
fixture.provisionerCapabilityLister = append(fixture.provisionerCapabilityLister, provisionerCapability)
fixture.csiDriverLister = append(fixture.csiDriverLister, csiDriver)
// Action expected
fixture.expectCreateSnapshotClassAction(snapshotClass)
fixture.expectUpdateStorageClassAction(storageClassUpdate)
fixture.expectCreateStorageClassCapabilitiesAction(storageClassCapability)
// Run test
fixture.run(getKey(storageClass, t))
}
func TestCreateStorageClassWithoutProvisionerCapability(t *testing.T) {
fixture := newFixture(t, true)
storageClass := newStorageClass("csi-example", "csi.example.com")
// Objects exist
fixture.storageObjects = append(fixture.storageObjects, storageClass)
fixture.storageClassLister = append(fixture.storageClassLister, storageClass)
storageClassUpdate := storageClass.DeepCopy()
storageClassUpdate.Annotations = map[string]string{annotationSupportSnapshot: "false"}
fixture.expectUpdateStorageClassAction(storageClassUpdate)
// Run test
fixture.run(getKey(storageClass, t))
}
func TestUpdateStorageClass(t *testing.T) {
storageClass := newStorageClass("csi-example", "csi.example.com")
storageClass.Annotations = map[string]string{annotationSupportSnapshot: "true"}
snapshotClass := newSnapshotClass(storageClass)
storageClassCapabilityUpdate := newStorageClassCapability(storageClass)
storageClassCapability := newStorageClassCapability(storageClass)
provisionerCapability := newProvisionerCapability(storageClass)
//old and new should have deference
storageClassCapability.Spec.Features.Volume.Create = !storageClassCapability.Spec.Features.Volume.Create
fixture := newFixture(t, true)
// Object exist
fixture.storageObjects = append(fixture.storageObjects, storageClass)
fixture.storageClassLister = append(fixture.storageClassLister, storageClass)
fixture.snapshotClassObjects = append(fixture.snapshotClassObjects, snapshotClass)
fixture.snapshotClassLister = append(fixture.snapshotClassLister, snapshotClass)
fixture.capabilityObjects = append(fixture.capabilityObjects, storageClassCapability, provisionerCapability)
fixture.storageClassCapabilityLister = append(fixture.storageClassCapabilityLister, storageClassCapability)
fixture.provisionerCapabilityLister = append(fixture.provisionerCapabilityLister, provisionerCapability)
// Action expected
fixture.expectUpdateStorageClassCapabilitiesAction(storageClassCapabilityUpdate)
// Run test
fixture.run(getKey(storageClass, t))
}
func TestUpdateStorageClassWithoutProvisionerCapability(t *testing.T) {
storageClass := newStorageClass("csi-example", "csi.example.com")
storageClass.Annotations = map[string]string{annotationSupportSnapshot: "true"}
storageClassUpdate := storageClass.DeepCopy()
storageClassUpdate.Annotations[annotationSupportSnapshot] = "false"
snapshotClass := newSnapshotClass(storageClass)
storageClassCapability := newStorageClassCapability(storageClass)
//old and new should have deference
storageClassCapability.Spec.Features.Volume.Create = !storageClassCapability.Spec.Features.Volume.Create
fixture := newFixture(t, true)
// Object exist
fixture.storageObjects = append(fixture.storageObjects, storageClass)
fixture.storageClassLister = append(fixture.storageClassLister, storageClass)
fixture.snapshotClassObjects = append(fixture.snapshotClassObjects, snapshotClass)
fixture.snapshotClassLister = append(fixture.snapshotClassLister, snapshotClass)
fixture.capabilityObjects = append(fixture.capabilityObjects, storageClassCapability)
fixture.storageClassCapabilityLister = append(fixture.storageClassCapabilityLister, storageClassCapability)
fixture.expectUpdateStorageClassAction(storageClassUpdate)
// Run test
@@ -403,19 +283,15 @@ func TestUpdateStorageClassWithoutProvisionerCapability(t *testing.T) {
func TestDeleteStorageClass(t *testing.T) {
storageClass := newStorageClass("csi-example", "csi.example.com")
snapshotClass := newSnapshotClass(storageClass)
storageClassCapability := newStorageClassCapability(storageClass)
fixture := newFixture(t, true)
// Object exist
fixture.storageObjects = append(fixture.storageObjects, storageClass)
fixture.snapshotClassObjects = append(fixture.snapshotClassObjects, snapshotClass)
fixture.snapshotClassLister = append(fixture.snapshotClassLister, snapshotClass)
fixture.capabilityObjects = append(fixture.capabilityObjects, storageClassCapability)
fixture.storageClassCapabilityLister = append(fixture.storageClassCapabilityLister, storageClassCapability)
// Action expected
fixture.expectDeleteSnapshotClassAction(snapshotClass)
fixture.expectDeleteStorageClassCapabilitiesAction(storageClassCapability)
// Run test
fixture.run(getKey(storageClass, t))
@@ -426,47 +302,78 @@ func TestCreateStorageClassNotSupportSnapshot(t *testing.T) {
fixture := newFixture(t, false)
storageClass := newStorageClass("csi-example", "csi.example.com")
storageClassUpdate := storageClass.DeepCopy()
storageClassUpdate.Annotations = map[string]string{annotationSupportSnapshot: "false"}
storageClassCapability := newStorageClassCapability(storageClass)
storageClassCapability.Spec.Features.Snapshot.Create = false
storageClassCapability.Spec.Features.Snapshot.List = false
provisionerCapability := newProvisionerCapability(storageClass)
storageClassUpdate.Annotations = map[string]string{annotationSupportSnapshot: "false", annotationSupportClone: "true"}
csiDriver := newCSIDriver("csi.example.com")
// Objects exist
fixture.storageObjects = append(fixture.storageObjects, storageClass)
fixture.storageClassLister = append(fixture.storageClassLister, storageClass)
fixture.capabilityObjects = append(fixture.capabilityObjects, provisionerCapability)
fixture.provisionerCapabilityLister = append(fixture.provisionerCapabilityLister, provisionerCapability)
fixture.csiDriverLister = append(fixture.csiDriverLister, csiDriver)
// Action expected
fixture.expectUpdateStorageClassAction(storageClassUpdate)
fixture.expectCreateStorageClassCapabilitiesAction(storageClassCapability)
// Run test
fixture.run(getKey(storageClass, t))
}
func TestCreateStorageClassNotHaveSnapshotCap(t *testing.T) {
// Storage has no snapshot capability
func TestStorageClassHadAnnotation(t *testing.T) {
fixture := newFixture(t, true)
storageClass := newStorageClass("csi-example", "csi.example.com")
storageClass.Annotations = map[string]string{annotationSupportSnapshot: "false", annotationSupportClone: "false"}
storageClassUpdate := storageClass.DeepCopy()
storageClassUpdate.Annotations = map[string]string{annotationSupportSnapshot: "false"}
storageClassCapability := newStorageClassCapability(storageClass)
storageClassCapability.Spec.Features.Snapshot.Create = false
provisionerCapability := newProvisionerCapability(storageClass)
provisionerCapability.Spec.Features.Snapshot.Create = false
csiDriver := newCSIDriver("csi.example.com")
snapshotClass := newSnapshotClass(storageClass)
// Objects exist
//Object exist
fixture.storageObjects = append(fixture.storageObjects, storageClass)
fixture.storageClassLister = append(fixture.storageClassLister, storageClass)
fixture.capabilityObjects = append(fixture.capabilityObjects, provisionerCapability)
fixture.provisionerCapabilityLister = append(fixture.provisionerCapabilityLister, provisionerCapability)
fixture.csiDriverLister = append(fixture.csiDriverLister, csiDriver)
// Action expected
//Action expected
fixture.expectCreateSnapshotClassAction(snapshotClass)
fixture.expectUpdateStorageClassAction(storageClassUpdate)
fixture.expectCreateStorageClassCapabilitiesAction(storageClassCapability)
// Run test
//Run test
fixture.run(getKey(storageClass, t))
}
func TestStorageClassHadOneAnnotation(t *testing.T) {
fixture := newFixture(t, true)
storageClass := newStorageClass("csi-example", "csi.example.com")
storageClass.Annotations = map[string]string{annotationSupportSnapshot: "false"}
storageClassUpdate := storageClass.DeepCopy()
storageClassUpdate.Annotations[annotationSupportClone] = "true"
csiDriver := newCSIDriver("csi.example.com")
snapshotClass := newSnapshotClass(storageClass)
//object exist
fixture.storageObjects = append(fixture.storageObjects, storageClass)
fixture.storageClassLister = append(fixture.storageClassLister, storageClass)
fixture.csiDriverLister = append(fixture.csiDriverLister, csiDriver)
//Action expected
fixture.expectCreateSnapshotClassAction(snapshotClass)
fixture.expectUpdateStorageClassAction(storageClassUpdate)
//Run test
fixture.run(getKey(storageClass, t))
}
func TestDeleteCSIDriver(t *testing.T) {
fixture := newFixture(t, true)
storageClass := newStorageClass("csi-example", "csi.example.com")
storageClass.Annotations = map[string]string{annotationSupportSnapshot: "false", annotationSupportClone: "false"}
storageClassUpdate := storageClass.DeepCopy()
storageClassUpdate.Annotations = map[string]string{}
//object exist
fixture.storageObjects = append(fixture.storageObjects, storageClass)
fixture.storageClassLister = append(fixture.storageClassLister, storageClass)
//Action expected
fixture.expectUpdateStorageClassAction(storageClassUpdate)
//Run test
fixture.run(getKey(storageClass, t))
}