Merge branch 'master' into status-52

This commit is contained in:
zhucan
2019-05-14 18:26:07 +08:00
committed by GitHub
45 changed files with 603 additions and 263 deletions

2
Gopkg.lock generated
View File

@@ -62,7 +62,6 @@
"ptypes", "ptypes",
"ptypes/any", "ptypes/any",
"ptypes/duration", "ptypes/duration",
"ptypes/timestamp",
"ptypes/wrappers", "ptypes/wrappers",
] ]
pruneopts = "NUT" pruneopts = "NUT"
@@ -754,7 +753,6 @@
"github.com/container-storage-interface/spec/lib/go/csi", "github.com/container-storage-interface/spec/lib/go/csi",
"github.com/golang/mock/gomock", "github.com/golang/mock/gomock",
"github.com/golang/protobuf/ptypes", "github.com/golang/protobuf/ptypes",
"github.com/golang/protobuf/ptypes/timestamp",
"github.com/kubernetes-csi/csi-lib-utils/connection", "github.com/kubernetes-csi/csi-lib-utils/connection",
"github.com/kubernetes-csi/csi-lib-utils/leaderelection", "github.com/kubernetes-csi/csi-lib-utils/leaderelection",
"github.com/kubernetes-csi/csi-lib-utils/rpc", "github.com/kubernetes-csi/csi-lib-utils/rpc",

View File

@@ -66,7 +66,7 @@ var (
snapshotNamePrefix = flag.String("snapshot-name-prefix", "snapshot", "Prefix to apply to the name of a created snapshot") snapshotNamePrefix = flag.String("snapshot-name-prefix", "snapshot", "Prefix to apply to the name of a created snapshot")
snapshotNameUUIDLength = flag.Int("snapshot-name-uuid-length", -1, "Length in characters for the generated uuid of a created snapshot. Defaults behavior is to NOT truncate.") snapshotNameUUIDLength = flag.Int("snapshot-name-uuid-length", -1, "Length in characters for the generated uuid of a created snapshot. Defaults behavior is to NOT truncate.")
showVersion = flag.Bool("version", false, "Show version.") showVersion = flag.Bool("version", false, "Show version.")
csiTimeout = flag.Duration("timeout", defaultCSITimeout, "The timeout for any RPCs to the CSI driver. Default is 10s.") csiTimeout = flag.Duration("timeout", defaultCSITimeout, "The timeout for any RPCs to the CSI driver. Default is 1 minute.")
leaderElection = flag.Bool("leader-election", false, "Enables leader election.") leaderElection = flag.Bool("leader-election", false, "Enables leader election.")
leaderElectionNamespace = flag.String("leader-election-namespace", "", "The namespace where the leader election resource exists. Defaults to the pod namespace if not set.") leaderElectionNamespace = flag.String("leader-election-namespace", "", "The namespace where the leader election resource exists. Defaults to the pod namespace if not set.")
@@ -184,9 +184,9 @@ func main() {
snapClient, snapClient,
kubeClient, kubeClient,
*snapshotterName, *snapshotterName,
factory.Volumesnapshot().V1alpha1().VolumeSnapshots(), factory.Snapshot().V1alpha1().VolumeSnapshots(),
factory.Volumesnapshot().V1alpha1().VolumeSnapshotContents(), factory.Snapshot().V1alpha1().VolumeSnapshotContents(),
factory.Volumesnapshot().V1alpha1().VolumeSnapshotClasses(), factory.Snapshot().V1alpha1().VolumeSnapshotClasses(),
coreFactory.Core().V1().PersistentVolumeClaims(), coreFactory.Core().V1().PersistentVolumeClaims(),
*createSnapshotContentRetryCount, *createSnapshotContentRetryCount,
*createSnapshotContentInterval, *createSnapshotContentInterval,

View File

@@ -25,7 +25,7 @@ rules:
verbs: ["get", "list", "watch"] verbs: ["get", "list", "watch"]
- apiGroups: [""] - apiGroups: [""]
resources: ["persistentvolumeclaims"] resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch"] verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"] - apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"] resources: ["storageclasses"]
verbs: ["get", "list", "watch"] verbs: ["get", "list", "watch"]

View File

@@ -72,7 +72,7 @@ spec:
serviceAccount: csi-snapshotter serviceAccount: csi-snapshotter
containers: containers:
- name: csi-provisioner - name: csi-provisioner
image: quay.io/k8scsi/csi-provisioner:v1.0.1 image: quay.io/k8scsi/csi-provisioner:v1.1.0
args: args:
- "--provisioner=csi-hostpath" - "--provisioner=csi-hostpath"
- "--csi-address=$(ADDRESS)" - "--csi-address=$(ADDRESS)"
@@ -85,7 +85,7 @@ spec:
- name: socket-dir - name: socket-dir
mountPath: /csi mountPath: /csi
- name: csi-snapshotter - name: csi-snapshotter
image: quay.io/k8scsi/csi-snapshotter:v1.0.1 image: quay.io/k8scsi/csi-snapshotter:v1.1.0
args: args:
- "--csi-address=$(ADDRESS)" - "--csi-address=$(ADDRESS)"
- "--connection-timeout=15s" - "--connection-timeout=15s"
@@ -98,7 +98,7 @@ spec:
- name: socket-dir - name: socket-dir
mountPath: /csi mountPath: /csi
- name: hostpath - name: hostpath
image: quay.io/k8scsi/hostpathplugin:v1.0.1 image: quay.io/k8scsi/hostpathplugin:v1.1.0
args: args:
- "--v=5" - "--v=5"
- "--endpoint=$(CSI_ENDPOINT)" - "--endpoint=$(CSI_ENDPOINT)"

View File

@@ -15,5 +15,6 @@ limitations under the License.
*/ */
// +k8s:deepcopy-gen=package // +k8s:deepcopy-gen=package
// +groupName=snapshot.storage.k8s.io
package v1alpha1 package v1alpha1

View File

@@ -1,7 +1,7 @@
// +build !ignore_autogenerated // +build !ignore_autogenerated
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@ limitations under the License.
package versioned package versioned
import ( import (
volumesnapshotv1alpha1 "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1" snapshotv1alpha1 "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1"
discovery "k8s.io/client-go/discovery" discovery "k8s.io/client-go/discovery"
rest "k8s.io/client-go/rest" rest "k8s.io/client-go/rest"
flowcontrol "k8s.io/client-go/util/flowcontrol" flowcontrol "k8s.io/client-go/util/flowcontrol"
@@ -27,27 +27,19 @@ import (
type Interface interface { type Interface interface {
Discovery() discovery.DiscoveryInterface Discovery() discovery.DiscoveryInterface
VolumesnapshotV1alpha1() volumesnapshotv1alpha1.VolumesnapshotV1alpha1Interface SnapshotV1alpha1() snapshotv1alpha1.SnapshotV1alpha1Interface
// Deprecated: please explicitly pick a version if possible.
Volumesnapshot() volumesnapshotv1alpha1.VolumesnapshotV1alpha1Interface
} }
// Clientset contains the clients for groups. Each group has exactly one // Clientset contains the clients for groups. Each group has exactly one
// version included in a Clientset. // version included in a Clientset.
type Clientset struct { type Clientset struct {
*discovery.DiscoveryClient *discovery.DiscoveryClient
volumesnapshotV1alpha1 *volumesnapshotv1alpha1.VolumesnapshotV1alpha1Client snapshotV1alpha1 *snapshotv1alpha1.SnapshotV1alpha1Client
} }
// VolumesnapshotV1alpha1 retrieves the VolumesnapshotV1alpha1Client // SnapshotV1alpha1 retrieves the SnapshotV1alpha1Client
func (c *Clientset) VolumesnapshotV1alpha1() volumesnapshotv1alpha1.VolumesnapshotV1alpha1Interface { func (c *Clientset) SnapshotV1alpha1() snapshotv1alpha1.SnapshotV1alpha1Interface {
return c.volumesnapshotV1alpha1 return c.snapshotV1alpha1
}
// Deprecated: Volumesnapshot retrieves the default version of VolumesnapshotClient.
// Please explicitly pick a version.
func (c *Clientset) Volumesnapshot() volumesnapshotv1alpha1.VolumesnapshotV1alpha1Interface {
return c.volumesnapshotV1alpha1
} }
// Discovery retrieves the DiscoveryClient // Discovery retrieves the DiscoveryClient
@@ -66,7 +58,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
} }
var cs Clientset var cs Clientset
var err error var err error
cs.volumesnapshotV1alpha1, err = volumesnapshotv1alpha1.NewForConfig(&configShallowCopy) cs.snapshotV1alpha1, err = snapshotv1alpha1.NewForConfig(&configShallowCopy)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -82,7 +74,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
// panics if there is an error in the config. // panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *Clientset { func NewForConfigOrDie(c *rest.Config) *Clientset {
var cs Clientset var cs Clientset
cs.volumesnapshotV1alpha1 = volumesnapshotv1alpha1.NewForConfigOrDie(c) cs.snapshotV1alpha1 = snapshotv1alpha1.NewForConfigOrDie(c)
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
return &cs return &cs
@@ -91,7 +83,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
// New creates a new Clientset for the given RESTClient. // New creates a new Clientset for the given RESTClient.
func New(c rest.Interface) *Clientset { func New(c rest.Interface) *Clientset {
var cs Clientset var cs Clientset
cs.volumesnapshotV1alpha1 = volumesnapshotv1alpha1.New(c) cs.snapshotV1alpha1 = snapshotv1alpha1.New(c)
cs.DiscoveryClient = discovery.NewDiscoveryClient(c) cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
return &cs return &cs

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -20,8 +20,8 @@ package fake
import ( import (
clientset "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned" clientset "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned"
volumesnapshotv1alpha1 "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1" snapshotv1alpha1 "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1"
fakevolumesnapshotv1alpha1 "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/fake" fakesnapshotv1alpha1 "github.com/kubernetes-csi/external-snapshotter/pkg/client/clientset/versioned/typed/volumesnapshot/v1alpha1/fake"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/discovery" "k8s.io/client-go/discovery"
@@ -71,12 +71,7 @@ func (c *Clientset) Discovery() discovery.DiscoveryInterface {
var _ clientset.Interface = &Clientset{} var _ clientset.Interface = &Clientset{}
// VolumesnapshotV1alpha1 retrieves the VolumesnapshotV1alpha1Client // SnapshotV1alpha1 retrieves the SnapshotV1alpha1Client
func (c *Clientset) VolumesnapshotV1alpha1() volumesnapshotv1alpha1.VolumesnapshotV1alpha1Interface { func (c *Clientset) SnapshotV1alpha1() snapshotv1alpha1.SnapshotV1alpha1Interface {
return &fakevolumesnapshotv1alpha1.FakeVolumesnapshotV1alpha1{Fake: &c.Fake} return &fakesnapshotv1alpha1.FakeSnapshotV1alpha1{Fake: &c.Fake}
}
// Volumesnapshot retrieves the VolumesnapshotV1alpha1Client
func (c *Clientset) Volumesnapshot() volumesnapshotv1alpha1.VolumesnapshotV1alpha1Interface {
return &fakevolumesnapshotv1alpha1.FakeVolumesnapshotV1alpha1{Fake: &c.Fake}
} }

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@ limitations under the License.
package fake package fake
import ( import (
volumesnapshotv1alpha1 "github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1" snapshotv1alpha1 "github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime" runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema" schema "k8s.io/apimachinery/pkg/runtime/schema"
@@ -31,7 +31,7 @@ var scheme = runtime.NewScheme()
var codecs = serializer.NewCodecFactory(scheme) var codecs = serializer.NewCodecFactory(scheme)
var parameterCodec = runtime.NewParameterCodec(scheme) var parameterCodec = runtime.NewParameterCodec(scheme)
var localSchemeBuilder = runtime.SchemeBuilder{ var localSchemeBuilder = runtime.SchemeBuilder{
volumesnapshotv1alpha1.AddToScheme, snapshotv1alpha1.AddToScheme,
} }
// AddToScheme adds all types of this clientset into the given scheme. This allows composition // AddToScheme adds all types of this clientset into the given scheme. This allows composition

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@ limitations under the License.
package scheme package scheme
import ( import (
volumesnapshotv1alpha1 "github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1" snapshotv1alpha1 "github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime" runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema" schema "k8s.io/apimachinery/pkg/runtime/schema"
@@ -31,7 +31,7 @@ var Scheme = runtime.NewScheme()
var Codecs = serializer.NewCodecFactory(Scheme) var Codecs = serializer.NewCodecFactory(Scheme)
var ParameterCodec = runtime.NewParameterCodec(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme)
var localSchemeBuilder = runtime.SchemeBuilder{ var localSchemeBuilder = runtime.SchemeBuilder{
volumesnapshotv1alpha1.AddToScheme, snapshotv1alpha1.AddToScheme,
} }
// AddToScheme adds all types of this clientset into the given scheme. This allows composition // AddToScheme adds all types of this clientset into the given scheme. This allows composition

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -30,13 +30,13 @@ import (
// FakeVolumeSnapshots implements VolumeSnapshotInterface // FakeVolumeSnapshots implements VolumeSnapshotInterface
type FakeVolumeSnapshots struct { type FakeVolumeSnapshots struct {
Fake *FakeVolumesnapshotV1alpha1 Fake *FakeSnapshotV1alpha1
ns string ns string
} }
var volumesnapshotsResource = schema.GroupVersionResource{Group: "volumesnapshot", Version: "v1alpha1", Resource: "volumesnapshots"} var volumesnapshotsResource = schema.GroupVersionResource{Group: "snapshot.storage.k8s.io", Version: "v1alpha1", Resource: "volumesnapshots"}
var volumesnapshotsKind = schema.GroupVersionKind{Group: "volumesnapshot", Version: "v1alpha1", Kind: "VolumeSnapshot"} var volumesnapshotsKind = schema.GroupVersionKind{Group: "snapshot.storage.k8s.io", Version: "v1alpha1", Kind: "VolumeSnapshot"}
// Get takes name of the volumeSnapshot, and returns the corresponding volumeSnapshot object, and an error if there is any. // Get takes name of the volumeSnapshot, and returns the corresponding volumeSnapshot object, and an error if there is any.
func (c *FakeVolumeSnapshots) Get(name string, options v1.GetOptions) (result *v1alpha1.VolumeSnapshot, err error) { func (c *FakeVolumeSnapshots) Get(name string, options v1.GetOptions) (result *v1alpha1.VolumeSnapshot, err error) {

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -24,25 +24,25 @@ import (
testing "k8s.io/client-go/testing" testing "k8s.io/client-go/testing"
) )
type FakeVolumesnapshotV1alpha1 struct { type FakeSnapshotV1alpha1 struct {
*testing.Fake *testing.Fake
} }
func (c *FakeVolumesnapshotV1alpha1) VolumeSnapshots(namespace string) v1alpha1.VolumeSnapshotInterface { func (c *FakeSnapshotV1alpha1) VolumeSnapshots(namespace string) v1alpha1.VolumeSnapshotInterface {
return &FakeVolumeSnapshots{c, namespace} return &FakeVolumeSnapshots{c, namespace}
} }
func (c *FakeVolumesnapshotV1alpha1) VolumeSnapshotClasses() v1alpha1.VolumeSnapshotClassInterface { func (c *FakeSnapshotV1alpha1) VolumeSnapshotClasses() v1alpha1.VolumeSnapshotClassInterface {
return &FakeVolumeSnapshotClasses{c} return &FakeVolumeSnapshotClasses{c}
} }
func (c *FakeVolumesnapshotV1alpha1) VolumeSnapshotContents() v1alpha1.VolumeSnapshotContentInterface { func (c *FakeSnapshotV1alpha1) VolumeSnapshotContents() v1alpha1.VolumeSnapshotContentInterface {
return &FakeVolumeSnapshotContents{c} return &FakeVolumeSnapshotContents{c}
} }
// RESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *FakeVolumesnapshotV1alpha1) RESTClient() rest.Interface { func (c *FakeSnapshotV1alpha1) RESTClient() rest.Interface {
var ret *rest.RESTClient var ret *rest.RESTClient
return ret return ret
} }

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -30,12 +30,12 @@ import (
// FakeVolumeSnapshotClasses implements VolumeSnapshotClassInterface // FakeVolumeSnapshotClasses implements VolumeSnapshotClassInterface
type FakeVolumeSnapshotClasses struct { type FakeVolumeSnapshotClasses struct {
Fake *FakeVolumesnapshotV1alpha1 Fake *FakeSnapshotV1alpha1
} }
var volumesnapshotclassesResource = schema.GroupVersionResource{Group: "volumesnapshot", Version: "v1alpha1", Resource: "volumesnapshotclasses"} var volumesnapshotclassesResource = schema.GroupVersionResource{Group: "snapshot.storage.k8s.io", Version: "v1alpha1", Resource: "volumesnapshotclasses"}
var volumesnapshotclassesKind = schema.GroupVersionKind{Group: "volumesnapshot", Version: "v1alpha1", Kind: "VolumeSnapshotClass"} var volumesnapshotclassesKind = schema.GroupVersionKind{Group: "snapshot.storage.k8s.io", Version: "v1alpha1", Kind: "VolumeSnapshotClass"}
// Get takes name of the volumeSnapshotClass, and returns the corresponding volumeSnapshotClass object, and an error if there is any. // Get takes name of the volumeSnapshotClass, and returns the corresponding volumeSnapshotClass object, and an error if there is any.
func (c *FakeVolumeSnapshotClasses) Get(name string, options v1.GetOptions) (result *v1alpha1.VolumeSnapshotClass, err error) { func (c *FakeVolumeSnapshotClasses) Get(name string, options v1.GetOptions) (result *v1alpha1.VolumeSnapshotClass, err error) {

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -30,12 +30,12 @@ import (
// FakeVolumeSnapshotContents implements VolumeSnapshotContentInterface // FakeVolumeSnapshotContents implements VolumeSnapshotContentInterface
type FakeVolumeSnapshotContents struct { type FakeVolumeSnapshotContents struct {
Fake *FakeVolumesnapshotV1alpha1 Fake *FakeSnapshotV1alpha1
} }
var volumesnapshotcontentsResource = schema.GroupVersionResource{Group: "volumesnapshot", Version: "v1alpha1", Resource: "volumesnapshotcontents"} var volumesnapshotcontentsResource = schema.GroupVersionResource{Group: "snapshot.storage.k8s.io", Version: "v1alpha1", Resource: "volumesnapshotcontents"}
var volumesnapshotcontentsKind = schema.GroupVersionKind{Group: "volumesnapshot", Version: "v1alpha1", Kind: "VolumeSnapshotContent"} var volumesnapshotcontentsKind = schema.GroupVersionKind{Group: "snapshot.storage.k8s.io", Version: "v1alpha1", Kind: "VolumeSnapshotContent"}
// Get takes name of the volumeSnapshotContent, and returns the corresponding volumeSnapshotContent object, and an error if there is any. // Get takes name of the volumeSnapshotContent, and returns the corresponding volumeSnapshotContent object, and an error if there is any.
func (c *FakeVolumeSnapshotContents) Get(name string, options v1.GetOptions) (result *v1alpha1.VolumeSnapshotContent, err error) { func (c *FakeVolumeSnapshotContents) Get(name string, options v1.GetOptions) (result *v1alpha1.VolumeSnapshotContent, err error) {

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -56,7 +56,7 @@ type volumeSnapshots struct {
} }
// newVolumeSnapshots returns a VolumeSnapshots // newVolumeSnapshots returns a VolumeSnapshots
func newVolumeSnapshots(c *VolumesnapshotV1alpha1Client, namespace string) *volumeSnapshots { func newVolumeSnapshots(c *SnapshotV1alpha1Client, namespace string) *volumeSnapshots {
return &volumeSnapshots{ return &volumeSnapshots{
client: c.RESTClient(), client: c.RESTClient(),
ns: namespace, ns: namespace,

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -25,32 +25,32 @@ import (
rest "k8s.io/client-go/rest" rest "k8s.io/client-go/rest"
) )
type VolumesnapshotV1alpha1Interface interface { type SnapshotV1alpha1Interface interface {
RESTClient() rest.Interface RESTClient() rest.Interface
VolumeSnapshotsGetter VolumeSnapshotsGetter
VolumeSnapshotClassesGetter VolumeSnapshotClassesGetter
VolumeSnapshotContentsGetter VolumeSnapshotContentsGetter
} }
// VolumesnapshotV1alpha1Client is used to interact with features provided by the volumesnapshot group. // SnapshotV1alpha1Client is used to interact with features provided by the snapshot.storage.k8s.io group.
type VolumesnapshotV1alpha1Client struct { type SnapshotV1alpha1Client struct {
restClient rest.Interface restClient rest.Interface
} }
func (c *VolumesnapshotV1alpha1Client) VolumeSnapshots(namespace string) VolumeSnapshotInterface { func (c *SnapshotV1alpha1Client) VolumeSnapshots(namespace string) VolumeSnapshotInterface {
return newVolumeSnapshots(c, namespace) return newVolumeSnapshots(c, namespace)
} }
func (c *VolumesnapshotV1alpha1Client) VolumeSnapshotClasses() VolumeSnapshotClassInterface { func (c *SnapshotV1alpha1Client) VolumeSnapshotClasses() VolumeSnapshotClassInterface {
return newVolumeSnapshotClasses(c) return newVolumeSnapshotClasses(c)
} }
func (c *VolumesnapshotV1alpha1Client) VolumeSnapshotContents() VolumeSnapshotContentInterface { func (c *SnapshotV1alpha1Client) VolumeSnapshotContents() VolumeSnapshotContentInterface {
return newVolumeSnapshotContents(c) return newVolumeSnapshotContents(c)
} }
// NewForConfig creates a new VolumesnapshotV1alpha1Client for the given config. // NewForConfig creates a new SnapshotV1alpha1Client for the given config.
func NewForConfig(c *rest.Config) (*VolumesnapshotV1alpha1Client, error) { func NewForConfig(c *rest.Config) (*SnapshotV1alpha1Client, error) {
config := *c config := *c
if err := setConfigDefaults(&config); err != nil { if err := setConfigDefaults(&config); err != nil {
return nil, err return nil, err
@@ -59,12 +59,12 @@ func NewForConfig(c *rest.Config) (*VolumesnapshotV1alpha1Client, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &VolumesnapshotV1alpha1Client{client}, nil return &SnapshotV1alpha1Client{client}, nil
} }
// NewForConfigOrDie creates a new VolumesnapshotV1alpha1Client for the given config and // NewForConfigOrDie creates a new SnapshotV1alpha1Client for the given config and
// panics if there is an error in the config. // panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *VolumesnapshotV1alpha1Client { func NewForConfigOrDie(c *rest.Config) *SnapshotV1alpha1Client {
client, err := NewForConfig(c) client, err := NewForConfig(c)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -72,9 +72,9 @@ func NewForConfigOrDie(c *rest.Config) *VolumesnapshotV1alpha1Client {
return client return client
} }
// New creates a new VolumesnapshotV1alpha1Client for the given RESTClient. // New creates a new SnapshotV1alpha1Client for the given RESTClient.
func New(c rest.Interface) *VolumesnapshotV1alpha1Client { func New(c rest.Interface) *SnapshotV1alpha1Client {
return &VolumesnapshotV1alpha1Client{c} return &SnapshotV1alpha1Client{c}
} }
func setConfigDefaults(config *rest.Config) error { func setConfigDefaults(config *rest.Config) error {
@@ -92,7 +92,7 @@ func setConfigDefaults(config *rest.Config) error {
// RESTClient returns a RESTClient that is used to communicate // RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation. // with API server by this client implementation.
func (c *VolumesnapshotV1alpha1Client) RESTClient() rest.Interface { func (c *SnapshotV1alpha1Client) RESTClient() rest.Interface {
if c == nil { if c == nil {
return nil return nil
} }

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -54,7 +54,7 @@ type volumeSnapshotClasses struct {
} }
// newVolumeSnapshotClasses returns a VolumeSnapshotClasses // newVolumeSnapshotClasses returns a VolumeSnapshotClasses
func newVolumeSnapshotClasses(c *VolumesnapshotV1alpha1Client) *volumeSnapshotClasses { func newVolumeSnapshotClasses(c *SnapshotV1alpha1Client) *volumeSnapshotClasses {
return &volumeSnapshotClasses{ return &volumeSnapshotClasses{
client: c.RESTClient(), client: c.RESTClient(),
} }

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -54,7 +54,7 @@ type volumeSnapshotContents struct {
} }
// newVolumeSnapshotContents returns a VolumeSnapshotContents // newVolumeSnapshotContents returns a VolumeSnapshotContents
func newVolumeSnapshotContents(c *VolumesnapshotV1alpha1Client) *volumeSnapshotContents { func newVolumeSnapshotContents(c *SnapshotV1alpha1Client) *volumeSnapshotContents {
return &volumeSnapshotContents{ return &volumeSnapshotContents{
client: c.RESTClient(), client: c.RESTClient(),
} }

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -172,9 +172,9 @@ type SharedInformerFactory interface {
ForResource(resource schema.GroupVersionResource) (GenericInformer, error) ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
Volumesnapshot() volumesnapshot.Interface Snapshot() volumesnapshot.Interface
} }
func (f *sharedInformerFactory) Volumesnapshot() volumesnapshot.Interface { func (f *sharedInformerFactory) Snapshot() volumesnapshot.Interface {
return volumesnapshot.New(f, f.namespace, f.tweakListOptions) return volumesnapshot.New(f, f.namespace, f.tweakListOptions)
} }

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -52,13 +52,13 @@ func (f *genericInformer) Lister() cache.GenericLister {
// TODO extend this to unknown resources with a client pool // TODO extend this to unknown resources with a client pool
func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
switch resource { switch resource {
// Group=volumesnapshot, Version=v1alpha1 // Group=snapshot.storage.k8s.io, Version=v1alpha1
case v1alpha1.SchemeGroupVersion.WithResource("volumesnapshots"): case v1alpha1.SchemeGroupVersion.WithResource("volumesnapshots"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Volumesnapshot().V1alpha1().VolumeSnapshots().Informer()}, nil return &genericInformer{resource: resource.GroupResource(), informer: f.Snapshot().V1alpha1().VolumeSnapshots().Informer()}, nil
case v1alpha1.SchemeGroupVersion.WithResource("volumesnapshotclasses"): case v1alpha1.SchemeGroupVersion.WithResource("volumesnapshotclasses"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Volumesnapshot().V1alpha1().VolumeSnapshotClasses().Informer()}, nil return &genericInformer{resource: resource.GroupResource(), informer: f.Snapshot().V1alpha1().VolumeSnapshotClasses().Informer()}, nil
case v1alpha1.SchemeGroupVersion.WithResource("volumesnapshotcontents"): case v1alpha1.SchemeGroupVersion.WithResource("volumesnapshotcontents"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Volumesnapshot().V1alpha1().VolumeSnapshotContents().Informer()}, nil return &genericInformer{resource: resource.GroupResource(), informer: f.Snapshot().V1alpha1().VolumeSnapshotContents().Informer()}, nil
} }

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@ limitations under the License.
// Code generated by informer-gen. DO NOT EDIT. // Code generated by informer-gen. DO NOT EDIT.
package volumesnapshot package snapshot
import ( import (
internalinterfaces "github.com/kubernetes-csi/external-snapshotter/pkg/client/informers/externalversions/internalinterfaces" internalinterfaces "github.com/kubernetes-csi/external-snapshotter/pkg/client/informers/externalversions/internalinterfaces"

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -61,13 +61,13 @@ func NewFilteredVolumeSnapshotInformer(client versioned.Interface, namespace str
if tweakListOptions != nil { if tweakListOptions != nil {
tweakListOptions(&options) tweakListOptions(&options)
} }
return client.VolumesnapshotV1alpha1().VolumeSnapshots(namespace).List(options) return client.SnapshotV1alpha1().VolumeSnapshots(namespace).List(options)
}, },
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil { if tweakListOptions != nil {
tweakListOptions(&options) tweakListOptions(&options)
} }
return client.VolumesnapshotV1alpha1().VolumeSnapshots(namespace).Watch(options) return client.SnapshotV1alpha1().VolumeSnapshots(namespace).Watch(options)
}, },
}, },
&volumesnapshotv1alpha1.VolumeSnapshot{}, &volumesnapshotv1alpha1.VolumeSnapshot{},

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -60,13 +60,13 @@ func NewFilteredVolumeSnapshotClassInformer(client versioned.Interface, resyncPe
if tweakListOptions != nil { if tweakListOptions != nil {
tweakListOptions(&options) tweakListOptions(&options)
} }
return client.VolumesnapshotV1alpha1().VolumeSnapshotClasses().List(options) return client.SnapshotV1alpha1().VolumeSnapshotClasses().List(options)
}, },
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil { if tweakListOptions != nil {
tweakListOptions(&options) tweakListOptions(&options)
} }
return client.VolumesnapshotV1alpha1().VolumeSnapshotClasses().Watch(options) return client.SnapshotV1alpha1().VolumeSnapshotClasses().Watch(options)
}, },
}, },
&volumesnapshotv1alpha1.VolumeSnapshotClass{}, &volumesnapshotv1alpha1.VolumeSnapshotClass{},

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -60,13 +60,13 @@ func NewFilteredVolumeSnapshotContentInformer(client versioned.Interface, resync
if tweakListOptions != nil { if tweakListOptions != nil {
tweakListOptions(&options) tweakListOptions(&options)
} }
return client.VolumesnapshotV1alpha1().VolumeSnapshotContents().List(options) return client.SnapshotV1alpha1().VolumeSnapshotContents().List(options)
}, },
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil { if tweakListOptions != nil {
tweakListOptions(&options) tweakListOptions(&options)
} }
return client.VolumesnapshotV1alpha1().VolumeSnapshotContents().Watch(options) return client.SnapshotV1alpha1().VolumeSnapshotContents().Watch(options)
}, },
}, },
&volumesnapshotv1alpha1.VolumeSnapshotContent{}, &volumesnapshotv1alpha1.VolumeSnapshotContent{},

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Kubernetes Authors. Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -30,9 +30,9 @@ import (
// Handler is responsible for handling VolumeSnapshot events from informer. // Handler is responsible for handling VolumeSnapshot events from informer.
type Handler interface { type Handler interface {
CreateSnapshot(snapshot *crdv1.VolumeSnapshot, volume *v1.PersistentVolume, parameters map[string]string, snapshotterCredentials map[string]string) (string, string, int64, int64, bool, error) CreateSnapshot(snapshot *crdv1.VolumeSnapshot, volume *v1.PersistentVolume, parameters map[string]string, snapshotterCredentials map[string]string) (string, string, time.Time, int64, bool, error)
DeleteSnapshot(content *crdv1.VolumeSnapshotContent, snapshotterCredentials map[string]string) error DeleteSnapshot(content *crdv1.VolumeSnapshotContent, snapshotterCredentials map[string]string) error
GetSnapshotStatus(content *crdv1.VolumeSnapshotContent) (bool, int64, int64, error) GetSnapshotStatus(content *crdv1.VolumeSnapshotContent) (bool, time.Time, int64, error)
} }
// csiHandler is a handler that calls CSI to create/delete volume snapshot. // csiHandler is a handler that calls CSI to create/delete volume snapshot.
@@ -58,18 +58,18 @@ func NewCSIHandler(
} }
} }
func (handler *csiHandler) CreateSnapshot(snapshot *crdv1.VolumeSnapshot, volume *v1.PersistentVolume, parameters map[string]string, snapshotterCredentials map[string]string) (string, string, int64, int64, bool, error) { func (handler *csiHandler) CreateSnapshot(snapshot *crdv1.VolumeSnapshot, volume *v1.PersistentVolume, parameters map[string]string, snapshotterCredentials map[string]string) (string, string, time.Time, int64, bool, error) {
ctx, cancel := context.WithTimeout(context.Background(), handler.timeout) ctx, cancel := context.WithTimeout(context.Background(), handler.timeout)
defer cancel() defer cancel()
snapshotName, err := makeSnapshotName(handler.snapshotNamePrefix, string(snapshot.UID), handler.snapshotNameUUIDLength) snapshotName, err := makeSnapshotName(handler.snapshotNamePrefix, string(snapshot.UID), handler.snapshotNameUUIDLength)
if err != nil { if err != nil {
return "", "", 0, 0, false, err return "", "", time.Time{}, 0, false, err
} }
newParameters, err := removePrefixedParameters(parameters) newParameters, err := removePrefixedParameters(parameters)
if err != nil { if err != nil {
return "", "", 0, 0, false, fmt.Errorf("failed to remove CSI Parameters of prefixed keys: %v", err) return "", "", time.Time{}, 0, false, fmt.Errorf("failed to remove CSI Parameters of prefixed keys: %v", err)
} }
return handler.snapshotter.CreateSnapshot(ctx, snapshotName, volume, newParameters, snapshotterCredentials) return handler.snapshotter.CreateSnapshot(ctx, snapshotName, volume, newParameters, snapshotterCredentials)
} }
@@ -89,16 +89,16 @@ func (handler *csiHandler) DeleteSnapshot(content *crdv1.VolumeSnapshotContent,
return nil return nil
} }
func (handler *csiHandler) GetSnapshotStatus(content *crdv1.VolumeSnapshotContent) (bool, int64, int64, error) { func (handler *csiHandler) GetSnapshotStatus(content *crdv1.VolumeSnapshotContent) (bool, time.Time, int64, error) {
if content.Spec.CSI == nil { if content.Spec.CSI == nil {
return false, 0, 0, fmt.Errorf("CSISnapshot not defined in spec") return false, time.Time{}, 0, fmt.Errorf("CSISnapshot not defined in spec")
} }
ctx, cancel := context.WithTimeout(context.Background(), handler.timeout) ctx, cancel := context.WithTimeout(context.Background(), handler.timeout)
defer cancel() defer cancel()
csiSnapshotStatus, timestamp, size, err := handler.snapshotter.GetSnapshotStatus(ctx, content.Spec.CSI.SnapshotHandle) csiSnapshotStatus, timestamp, size, err := handler.snapshotter.GetSnapshotStatus(ctx, content.Spec.CSI.SnapshotHandle)
if err != nil { if err != nil {
return false, 0, 0, fmt.Errorf("failed to list snapshot content %s: %q", content.Name, err) return false, time.Time{}, 0, fmt.Errorf("failed to list snapshot content %s: %q", content.Name, err)
} }
return csiSnapshotStatus, timestamp, size, nil return csiSnapshotStatus, timestamp, size, nil

View File

@@ -21,6 +21,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"reflect" "reflect"
sysruntime "runtime"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@@ -53,6 +54,7 @@ import (
"k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
"k8s.io/klog" "k8s.io/klog"
"k8s.io/kubernetes/pkg/util/slice"
) )
// This is a unit test framework for snapshot controller. // This is a unit test framework for snapshot controller.
@@ -110,7 +112,8 @@ type controllerTest struct {
// List of expected CSI list snapshot calls // List of expected CSI list snapshot calls
expectedListCalls []listCall expectedListCalls []listCall
// Function to call as the test. // Function to call as the test.
test testCall test testCall
expectSuccess bool
} }
type testCall func(ctrl *csiSnapshotController, reactor *snapshotReactor, test controllerTest) error type testCall func(ctrl *csiSnapshotController, reactor *snapshotReactor, test controllerTest) error
@@ -177,6 +180,11 @@ func withContentFinalizer(content *crdv1.VolumeSnapshotContent) *crdv1.VolumeSna
return content return content
} }
func withPVCFinalizer(pvc *v1.PersistentVolumeClaim) *v1.PersistentVolumeClaim {
pvc.ObjectMeta.Finalizers = append(pvc.ObjectMeta.Finalizers, PVCFinalizer)
return pvc
}
// React is a callback called by fake kubeClient from the controller. // React is a callback called by fake kubeClient from the controller.
// In other words, every snapshot/content change performed by the controller ends // In other words, every snapshot/content change performed by the controller ends
// here. // here.
@@ -331,6 +339,32 @@ func (r *snapshotReactor) React(action core.Action) (handled bool, ret runtime.O
klog.V(4).Infof("GetClaim: claim %s not found", name) klog.V(4).Infof("GetClaim: claim %s not found", name)
return true, nil, fmt.Errorf("cannot find claim %s", name) return true, nil, fmt.Errorf("cannot find claim %s", name)
case action.Matches("update", "persistentvolumeclaims"):
obj := action.(core.UpdateAction).GetObject()
claim := obj.(*v1.PersistentVolumeClaim)
// Check and bump object version
storedClaim, found := r.claims[claim.Name]
if found {
storedVer, _ := strconv.Atoi(storedClaim.ResourceVersion)
requestedVer, _ := strconv.Atoi(claim.ResourceVersion)
if storedVer != requestedVer {
return true, obj, errVersionConflict
}
// Don't modify the existing object
claim = claim.DeepCopy()
claim.ResourceVersion = strconv.Itoa(storedVer + 1)
} else {
return true, nil, fmt.Errorf("cannot update claim %s: claim not found", claim.Name)
}
// Store the updated object to appropriate places.
r.claims[claim.Name] = claim
r.changedObjects = append(r.changedObjects, claim)
r.changedSinceLastSync++
klog.V(4).Infof("saved updated claim %s", claim.Name)
return true, claim, nil
case action.Matches("get", "storageclasses"): case action.Matches("get", "storageclasses"):
name := action.(core.GetAction).GetName() name := action.(core.GetAction).GetName()
storageClass, found := r.storageClasses[name] storageClass, found := r.storageClasses[name]
@@ -550,6 +584,9 @@ func (r *snapshotReactor) syncAll() {
for _, v := range r.contents { for _, v := range r.contents {
r.changedObjects = append(r.changedObjects, v) r.changedObjects = append(r.changedObjects, v)
} }
for _, pvc := range r.claims {
r.changedObjects = append(r.changedObjects, pvc)
}
r.changedSinceLastSync = 0 r.changedSinceLastSync = 0
} }
@@ -699,6 +736,7 @@ func newSnapshotReactor(kubeClient *kubefake.Clientset, client *fake.Clientset,
client.AddReactor("delete", "volumesnapshotcontents", reactor.React) client.AddReactor("delete", "volumesnapshotcontents", reactor.React)
client.AddReactor("delete", "volumesnapshots", reactor.React) client.AddReactor("delete", "volumesnapshots", reactor.React)
kubeClient.AddReactor("get", "persistentvolumeclaims", reactor.React) kubeClient.AddReactor("get", "persistentvolumeclaims", reactor.React)
kubeClient.AddReactor("update", "persistentvolumeclaims", reactor.React)
kubeClient.AddReactor("get", "persistentvolumes", reactor.React) kubeClient.AddReactor("get", "persistentvolumes", reactor.React)
kubeClient.AddReactor("get", "storageclasses", reactor.React) kubeClient.AddReactor("get", "storageclasses", reactor.React)
kubeClient.AddReactor("get", "secrets", reactor.React) kubeClient.AddReactor("get", "secrets", reactor.React)
@@ -728,9 +766,9 @@ func newTestController(kubeClient kubernetes.Interface, clientset clientset.Inte
clientset, clientset,
kubeClient, kubeClient,
mockDriverName, mockDriverName,
informerFactory.Volumesnapshot().V1alpha1().VolumeSnapshots(), informerFactory.Snapshot().V1alpha1().VolumeSnapshots(),
informerFactory.Volumesnapshot().V1alpha1().VolumeSnapshotContents(), informerFactory.Snapshot().V1alpha1().VolumeSnapshotContents(),
informerFactory.Volumesnapshot().V1alpha1().VolumeSnapshotClasses(), informerFactory.Snapshot().V1alpha1().VolumeSnapshotClasses(),
coreFactory.Core().V1().PersistentVolumeClaims(), coreFactory.Core().V1().PersistentVolumeClaims(),
3, 3,
5*time.Millisecond, 5*time.Millisecond,
@@ -746,6 +784,7 @@ func newTestController(kubeClient kubernetes.Interface, clientset clientset.Inte
ctrl.contentListerSynced = alwaysReady ctrl.contentListerSynced = alwaysReady
ctrl.snapshotListerSynced = alwaysReady ctrl.snapshotListerSynced = alwaysReady
ctrl.classListerSynced = alwaysReady ctrl.classListerSynced = alwaysReady
ctrl.pvcListerSynced = alwaysReady
return ctrl, nil return ctrl, nil
} }
@@ -845,7 +884,7 @@ func newSnapshotArray(name, className, boundToContent, snapshotUID, claimName st
} }
// newClaim returns a new claim with given attributes // newClaim returns a new claim with given attributes
func newClaim(name, claimUID, capacity, boundToVolume string, phase v1.PersistentVolumeClaimPhase, class *string) *v1.PersistentVolumeClaim { func newClaim(name, claimUID, capacity, boundToVolume string, phase v1.PersistentVolumeClaimPhase, class *string, bFinalizer bool) *v1.PersistentVolumeClaim {
claim := v1.PersistentVolumeClaim{ claim := v1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
@@ -877,6 +916,9 @@ func newClaim(name, claimUID, capacity, boundToVolume string, phase v1.Persisten
claim.Status.Capacity = claim.Spec.Resources.Requests claim.Status.Capacity = claim.Spec.Resources.Requests
} }
if bFinalizer {
return withPVCFinalizer(&claim)
}
return &claim return &claim
} }
@@ -884,7 +926,15 @@ func newClaim(name, claimUID, capacity, boundToVolume string, phase v1.Persisten
// newClaim() with the same parameters. // newClaim() with the same parameters.
func newClaimArray(name, claimUID, capacity, boundToVolume string, phase v1.PersistentVolumeClaimPhase, class *string) []*v1.PersistentVolumeClaim { func newClaimArray(name, claimUID, capacity, boundToVolume string, phase v1.PersistentVolumeClaimPhase, class *string) []*v1.PersistentVolumeClaim {
return []*v1.PersistentVolumeClaim{ return []*v1.PersistentVolumeClaim{
newClaim(name, claimUID, capacity, boundToVolume, phase, class), newClaim(name, claimUID, capacity, boundToVolume, phase, class, false),
}
}
// newClaimArrayFinalizer returns array with a single claim that would be returned by
// newClaim() with the same parameters plus finalizer.
func newClaimArrayFinalizer(name, claimUID, capacity, boundToVolume string, phase v1.PersistentVolumeClaimPhase, class *string) []*v1.PersistentVolumeClaim {
return []*v1.PersistentVolumeClaim{
newClaim(name, claimUID, capacity, boundToVolume, phase, class, true),
} }
} }
@@ -961,6 +1011,14 @@ func testSyncContent(ctrl *csiSnapshotController, reactor *snapshotReactor, test
return ctrl.syncContent(test.initialContents[0]) return ctrl.syncContent(test.initialContents[0])
} }
func testAddPVCFinalizer(ctrl *csiSnapshotController, reactor *snapshotReactor, test controllerTest) error {
return ctrl.ensureSnapshotSourceFinalizer(test.initialSnapshots[0])
}
func testRemovePVCFinalizer(ctrl *csiSnapshotController, reactor *snapshotReactor, test controllerTest) error {
return ctrl.checkandRemoveSnapshotSourceFinalizer(test.initialSnapshots[0])
}
var ( var (
classEmpty string classEmpty string
classGold = "gold" classGold = "gold"
@@ -1097,6 +1155,113 @@ func runSyncTests(t *testing.T, tests []controllerTest, snapshotClasses []*crdv1
} }
} }
// This tests ensureSnapshotSourceFinalizer and checkandRemoveSnapshotSourceFinalizer
func runPVCFinalizerTests(t *testing.T, tests []controllerTest, snapshotClasses []*crdv1.VolumeSnapshotClass) {
snapshotscheme.AddToScheme(scheme.Scheme)
for _, test := range tests {
klog.V(4).Infof("starting test %q", test.name)
// Initialize the controller
kubeClient := &kubefake.Clientset{}
client := &fake.Clientset{}
ctrl, err := newTestController(kubeClient, client, nil, t, test)
if err != nil {
t.Fatalf("Test %q construct persistent content failed: %v", test.name, err)
}
reactor := newSnapshotReactor(kubeClient, client, ctrl, nil, nil, test.errors)
for _, snapshot := range test.initialSnapshots {
ctrl.snapshotStore.Add(snapshot)
reactor.snapshots[snapshot.Name] = snapshot
}
for _, content := range test.initialContents {
if ctrl.isDriverMatch(test.initialContents[0]) {
ctrl.contentStore.Add(content)
reactor.contents[content.Name] = content
}
}
pvcIndexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{})
for _, claim := range test.initialClaims {
reactor.claims[claim.Name] = claim
pvcIndexer.Add(claim)
}
ctrl.pvcLister = corelisters.NewPersistentVolumeClaimLister(pvcIndexer)
for _, volume := range test.initialVolumes {
reactor.volumes[volume.Name] = volume
}
for _, storageClass := range test.initialStorageClasses {
reactor.storageClasses[storageClass.Name] = storageClass
}
for _, secret := range test.initialSecrets {
reactor.secrets[secret.Name] = secret
}
// Inject classes into controller via a custom lister.
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{})
for _, class := range snapshotClasses {
indexer.Add(class)
}
ctrl.classLister = storagelisters.NewVolumeSnapshotClassLister(indexer)
// Run the tested functions
err = test.test(ctrl, reactor, test)
if err != nil {
t.Errorf("Test %q failed: %v", test.name, err)
}
// Verify PVCFinalizer tests results
evaluatePVCFinalizerTests(ctrl, reactor, test, t)
}
}
// Evaluate PVCFinalizer tests results
func evaluatePVCFinalizerTests(ctrl *csiSnapshotController, reactor *snapshotReactor, test controllerTest, t *testing.T) {
// Evaluate results
bHasPVCFinalizer := false
name := sysruntime.FuncForPC(reflect.ValueOf(test.test).Pointer()).Name()
index := strings.LastIndex(name, ".")
if index == -1 {
t.Errorf("Test %q: failed to test finalizer - invalid test call name [%s]", test.name, name)
return
}
names := []rune(name)
funcName := string(names[index+1 : len(name)])
klog.V(4).Infof("test %q: PVCFinalizer test func name: [%s]", test.name, funcName)
if funcName == "testAddPVCFinalizer" {
for _, pvc := range reactor.claims {
if test.initialClaims[0].Name == pvc.Name {
if !slice.ContainsString(test.initialClaims[0].ObjectMeta.Finalizers, PVCFinalizer, nil) && slice.ContainsString(pvc.ObjectMeta.Finalizers, PVCFinalizer, nil) {
klog.V(4).Infof("test %q succeeded. PVCFinalizer is added to PVC %s", test.name, pvc.Name)
bHasPVCFinalizer = true
}
break
}
}
if test.expectSuccess && !bHasPVCFinalizer {
t.Errorf("Test %q: failed to add finalizer to PVC %s", test.name, test.initialClaims[0].Name)
}
}
bHasPVCFinalizer = true
if funcName == "testRemovePVCFinalizer" {
for _, pvc := range reactor.claims {
if test.initialClaims[0].Name == pvc.Name {
if slice.ContainsString(test.initialClaims[0].ObjectMeta.Finalizers, PVCFinalizer, nil) && !slice.ContainsString(pvc.ObjectMeta.Finalizers, PVCFinalizer, nil) {
klog.V(4).Infof("test %q succeeded. PVCFinalizer is removed from PVC %s", test.name, pvc.Name)
bHasPVCFinalizer = false
}
break
}
}
if test.expectSuccess && bHasPVCFinalizer {
t.Errorf("Test %q: failed to remove finalizer from PVC %s", test.name, test.initialClaims[0].Name)
}
}
}
func getSize(size int64) *resource.Quantity { func getSize(size int64) *resource.Quantity {
return resource.NewQuantity(size, resource.BinarySI) return resource.NewQuantity(size, resource.BinarySI)
} }
@@ -1126,7 +1291,7 @@ type listCall struct {
snapshotID string snapshotID string
// information to return // information to return
readyToUse bool readyToUse bool
createTime int64 createTime time.Time
size int64 size int64
err error err error
} }
@@ -1144,12 +1309,12 @@ type createCall struct {
parameters map[string]string parameters map[string]string
secrets map[string]string secrets map[string]string
// information to return // information to return
driverName string driverName string
snapshotId string snapshotId string
timestamp int64 creationTime time.Time
size int64 size int64
readyToUse bool readyToUse bool
err error err error
} }
// Fake SnapShotter implementation that check that Attach/Detach is called // Fake SnapShotter implementation that check that Attach/Detach is called
@@ -1164,10 +1329,10 @@ type fakeSnapshotter struct {
t *testing.T t *testing.T
} }
func (f *fakeSnapshotter) CreateSnapshot(ctx context.Context, snapshotName string, volume *v1.PersistentVolume, parameters map[string]string, snapshotterCredentials map[string]string) (string, string, int64, int64, bool, error) { func (f *fakeSnapshotter) CreateSnapshot(ctx context.Context, snapshotName string, volume *v1.PersistentVolume, parameters map[string]string, snapshotterCredentials map[string]string) (string, string, time.Time, int64, bool, error) {
if f.createCallCounter >= len(f.createCalls) { if f.createCallCounter >= len(f.createCalls) {
f.t.Errorf("Unexpected CSI Create Snapshot call: snapshotName=%s, volume=%v, index: %d, calls: %+v", snapshotName, volume.Name, f.createCallCounter, f.createCalls) f.t.Errorf("Unexpected CSI Create Snapshot call: snapshotName=%s, volume=%v, index: %d, calls: %+v", snapshotName, volume.Name, f.createCallCounter, f.createCalls)
return "", "", 0, 0, false, fmt.Errorf("unexpected call") return "", "", time.Time{}, 0, false, fmt.Errorf("unexpected call")
} }
call := f.createCalls[f.createCallCounter] call := f.createCalls[f.createCallCounter]
f.createCallCounter++ f.createCallCounter++
@@ -1194,10 +1359,10 @@ func (f *fakeSnapshotter) CreateSnapshot(ctx context.Context, snapshotName strin
} }
if err != nil { if err != nil {
return "", "", 0, 0, false, fmt.Errorf("unexpected call") return "", "", time.Time{}, 0, false, fmt.Errorf("unexpected call")
} }
return call.driverName, call.snapshotId, call.timestamp, call.size, call.readyToUse, call.err return call.driverName, call.snapshotId, call.creationTime, call.size, call.readyToUse, call.err
} }
func (f *fakeSnapshotter) DeleteSnapshot(ctx context.Context, snapshotID string, snapshotterCredentials map[string]string) error { func (f *fakeSnapshotter) DeleteSnapshot(ctx context.Context, snapshotID string, snapshotterCredentials map[string]string) error {
@@ -1226,10 +1391,10 @@ func (f *fakeSnapshotter) DeleteSnapshot(ctx context.Context, snapshotID string,
return call.err return call.err
} }
func (f *fakeSnapshotter) GetSnapshotStatus(ctx context.Context, snapshotID string) (bool, int64, int64, error) { func (f *fakeSnapshotter) GetSnapshotStatus(ctx context.Context, snapshotID string) (bool, time.Time, int64, error) {
if f.listCallCounter >= len(f.listCalls) { if f.listCallCounter >= len(f.listCalls) {
f.t.Errorf("Unexpected CSI list Snapshot call: snapshotID=%s, index: %d, calls: %+v", snapshotID, f.createCallCounter, f.createCalls) f.t.Errorf("Unexpected CSI list Snapshot call: snapshotID=%s, index: %d, calls: %+v", snapshotID, f.createCallCounter, f.createCalls)
return false, 0, 0, fmt.Errorf("unexpected call") return false, time.Time{}, 0, fmt.Errorf("unexpected call")
} }
call := f.listCalls[f.listCallCounter] call := f.listCalls[f.listCallCounter]
f.listCallCounter++ f.listCallCounter++
@@ -1241,7 +1406,7 @@ func (f *fakeSnapshotter) GetSnapshotStatus(ctx context.Context, snapshotID stri
} }
if err != nil { if err != nil {
return false, 0, 0, fmt.Errorf("unexpected call") return false, time.Time{}, 0, fmt.Errorf("unexpected call")
} }
return call.readyToUse, call.createTime, call.size, call.err return call.readyToUse, call.createTime, call.size, call.err

View File

@@ -192,11 +192,19 @@ func (ctrl *csiSnapshotController) syncSnapshot(snapshot *crdv1.VolumeSnapshot)
return ctrl.addSnapshotFinalizer(snapshot) return ctrl.addSnapshotFinalizer(snapshot)
} }
klog.V(5).Infof("syncSnapshot[%s]: check if we should remove finalizer on snapshot source and remove it if we can", snapshotKey(snapshot))
// Check if we should remove finalizer on snapshot source and remove it if we can.
errFinalizer := ctrl.checkandRemoveSnapshotSourceFinalizer(snapshot)
if errFinalizer != nil {
klog.Errorf("error check and remove snapshot source finalizer for snapshot [%s]: %v", snapshot.Name, errFinalizer)
// Log an event and keep the original error from syncUnready/ReadySnapshot
ctrl.eventRecorder.Event(snapshot, v1.EventTypeWarning, "ErrorSnapshotSourceFinalizer", "Error check and remove PVC Finalizer for VolumeSnapshot")
}
if !snapshot.Status.ReadyToUse { if !snapshot.Status.ReadyToUse {
return ctrl.syncUnreadySnapshot(snapshot) return ctrl.syncUnreadySnapshot(snapshot)
} }
return ctrl.syncReadySnapshot(snapshot) return ctrl.syncReadySnapshot(snapshot)
} }
// syncReadySnapshot checks the snapshot which has been bound to snapshot content successfully before. // syncReadySnapshot checks the snapshot which has been bound to snapshot content successfully before.
@@ -367,7 +375,6 @@ func (ctrl *csiSnapshotController) createSnapshot(snapshot *crdv1.VolumeSnapshot
// We will get an "snapshot update" event soon, this is not a big error // We will get an "snapshot update" event soon, this is not a big error
klog.V(4).Infof("createSnapshot [%s]: cannot update internal cache: %v", snapshotKey(snapshotObj), updateErr) klog.V(4).Infof("createSnapshot [%s]: cannot update internal cache: %v", snapshotKey(snapshotObj), updateErr)
} }
return nil return nil
}) })
return nil return nil
@@ -451,7 +458,7 @@ func IsSnapshotBound(snapshot *crdv1.VolumeSnapshot, content *crdv1.VolumeSnapsh
// isSnapshotConentBeingUsed checks if snapshot content is bound to snapshot. // isSnapshotConentBeingUsed checks if snapshot content is bound to snapshot.
func (ctrl *csiSnapshotController) isSnapshotContentBeingUsed(content *crdv1.VolumeSnapshotContent) bool { func (ctrl *csiSnapshotController) isSnapshotContentBeingUsed(content *crdv1.VolumeSnapshotContent) bool {
if content.Spec.VolumeSnapshotRef != nil { if content.Spec.VolumeSnapshotRef != nil {
snapshotObj, err := ctrl.clientset.VolumesnapshotV1alpha1().VolumeSnapshots(content.Spec.VolumeSnapshotRef.Namespace).Get(content.Spec.VolumeSnapshotRef.Name, metav1.GetOptions{}) snapshotObj, err := ctrl.clientset.SnapshotV1alpha1().VolumeSnapshots(content.Spec.VolumeSnapshotRef.Namespace).Get(content.Spec.VolumeSnapshotRef.Name, metav1.GetOptions{})
if err != nil { if err != nil {
klog.Infof("isSnapshotContentBeingUsed: Cannot get snapshot %s from api server: [%v]. VolumeSnapshot object may be deleted already.", content.Spec.VolumeSnapshotRef.Name, err) klog.Infof("isSnapshotContentBeingUsed: Cannot get snapshot %s from api server: [%v]. VolumeSnapshot object may be deleted already.", content.Spec.VolumeSnapshotRef.Name, err)
return false return false
@@ -503,7 +510,7 @@ func (ctrl *csiSnapshotController) checkandBindSnapshotContent(snapshot *crdv1.V
contentClone.Spec.VolumeSnapshotRef.UID = snapshot.UID contentClone.Spec.VolumeSnapshotRef.UID = snapshot.UID
className := *(snapshot.Spec.VolumeSnapshotClassName) className := *(snapshot.Spec.VolumeSnapshotClassName)
contentClone.Spec.VolumeSnapshotClassName = &className contentClone.Spec.VolumeSnapshotClassName = &className
newContent, err := ctrl.clientset.VolumesnapshotV1alpha1().VolumeSnapshotContents().Update(contentClone) newContent, err := ctrl.clientset.SnapshotV1alpha1().VolumeSnapshotContents().Update(contentClone)
if err != nil { if err != nil {
klog.V(4).Infof("updating VolumeSnapshotContent[%s] error status failed %v", newContent.Name, err) klog.V(4).Infof("updating VolumeSnapshotContent[%s] error status failed %v", newContent.Name, err)
return nil, err return nil, err
@@ -556,7 +563,7 @@ func (ctrl *csiSnapshotController) getCreateSnapshotInput(snapshot *crdv1.Volume
func (ctrl *csiSnapshotController) checkandUpdateBoundSnapshotStatusOperation(snapshot *crdv1.VolumeSnapshot, content *crdv1.VolumeSnapshotContent) (*crdv1.VolumeSnapshot, error) { func (ctrl *csiSnapshotController) checkandUpdateBoundSnapshotStatusOperation(snapshot *crdv1.VolumeSnapshot, content *crdv1.VolumeSnapshotContent) (*crdv1.VolumeSnapshot, error) {
var err error var err error
var timestamp int64 var creationTime time.Time
var size int64 var size int64
var readyToUse = false var readyToUse = false
var driverName string var driverName string
@@ -564,7 +571,7 @@ func (ctrl *csiSnapshotController) checkandUpdateBoundSnapshotStatusOperation(sn
if snapshot.Spec.Source == nil { if snapshot.Spec.Source == nil {
klog.V(5).Infof("checkandUpdateBoundSnapshotStatusOperation: checking whether snapshot [%s] is pre-bound to content [%s]", snapshot.Name, content.Name) klog.V(5).Infof("checkandUpdateBoundSnapshotStatusOperation: checking whether snapshot [%s] is pre-bound to content [%s]", snapshot.Name, content.Name)
readyToUse, timestamp, size, err = ctrl.handler.GetSnapshotStatus(content) readyToUse, creationTime, size, err = ctrl.handler.GetSnapshotStatus(content)
if err != nil { if err != nil {
klog.Errorf("checkandUpdateBoundSnapshotStatusOperation: failed to call get snapshot status to check whether snapshot is ready to use %q", err) klog.Errorf("checkandUpdateBoundSnapshotStatusOperation: failed to call get snapshot status to check whether snapshot is ready to use %q", err)
return nil, err return nil, err
@@ -577,18 +584,18 @@ func (ctrl *csiSnapshotController) checkandUpdateBoundSnapshotStatusOperation(sn
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get input parameters to create snapshot %s: %q", snapshot.Name, err) return nil, fmt.Errorf("failed to get input parameters to create snapshot %s: %q", snapshot.Name, err)
} }
driverName, snapshotID, timestamp, size, readyToUse, err = ctrl.handler.CreateSnapshot(snapshot, volume, class.Parameters, snapshotterCredentials) driverName, snapshotID, creationTime, size, readyToUse, err = ctrl.handler.CreateSnapshot(snapshot, volume, class.Parameters, snapshotterCredentials)
if err != nil { if err != nil {
klog.Errorf("checkandUpdateBoundSnapshotStatusOperation: failed to call create snapshot to check whether the snapshot is ready to use %q", err) klog.Errorf("checkandUpdateBoundSnapshotStatusOperation: failed to call create snapshot to check whether the snapshot is ready to use %q", err)
return nil, err return nil, err
} }
} }
klog.V(5).Infof("checkandUpdateBoundSnapshotStatusOperation: driver %s, snapshotId %s, timestamp %d, size %d, readyToUse %t", driverName, snapshotID, timestamp, size, readyToUse) klog.V(5).Infof("checkandUpdateBoundSnapshotStatusOperation: driver %s, snapshotId %s, creationTime %v, size %d, readyToUse %t", driverName, snapshotID, creationTime, size, readyToUse)
if timestamp == 0 { if creationTime.IsZero() {
timestamp = time.Now().UnixNano() creationTime = time.Now()
} }
newSnapshot, err := ctrl.updateSnapshotStatus(snapshot, readyToUse, timestamp, size, IsSnapshotBound(snapshot, content)) newSnapshot, err := ctrl.updateSnapshotStatus(snapshot, readyToUse, creationTime, size, IsSnapshotBound(snapshot, content))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -612,22 +619,31 @@ func (ctrl *csiSnapshotController) createSnapshotOperation(snapshot *crdv1.Volum
return snapshot, nil return snapshot, nil
} }
// If PVC is not being deleted and finalizer is not added yet, a finalizer should be added.
klog.V(5).Infof("createSnapshotOperation: Check if PVC is not being deleted and add Finalizer for source of snapshot [%s] if needed", snapshot.Name)
err := ctrl.ensureSnapshotSourceFinalizer(snapshot)
if err != nil {
klog.Errorf("createSnapshotOperation failed to add finalizer for source of snapshot %s", err)
return nil, err
}
class, volume, contentName, snapshotterCredentials, err := ctrl.getCreateSnapshotInput(snapshot) class, volume, contentName, snapshotterCredentials, err := ctrl.getCreateSnapshotInput(snapshot)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get input parameters to create snapshot %s: %q", snapshot.Name, err) return nil, fmt.Errorf("failed to get input parameters to create snapshot %s: %q", snapshot.Name, err)
} }
driverName, snapshotID, timestamp, size, readyToUse, err := ctrl.handler.CreateSnapshot(snapshot, volume, class.Parameters, snapshotterCredentials) driverName, snapshotID, creationTime, size, readyToUse, err := ctrl.handler.CreateSnapshot(snapshot, volume, class.Parameters, snapshotterCredentials)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to take snapshot of the volume, %s: %q", volume.Name, err) return nil, fmt.Errorf("failed to take snapshot of the volume, %s: %q", volume.Name, err)
} }
klog.V(5).Infof("Created snapshot: driver %s, snapshotId %s, timestamp %d, size %d, readyToUse %t", driverName, snapshotID, timestamp, size, readyToUse)
klog.V(5).Infof("Created snapshot: driver %s, snapshotId %s, creationTime %v, size %d, readyToUse %t", driverName, snapshotID, creationTime, size, readyToUse)
var newSnapshot *crdv1.VolumeSnapshot var newSnapshot *crdv1.VolumeSnapshot
// Update snapshot status with timestamp // Update snapshot status with creationTime
for i := 0; i < ctrl.createSnapshotContentRetryCount; i++ { for i := 0; i < ctrl.createSnapshotContentRetryCount; i++ {
klog.V(5).Infof("createSnapshot [%s]: trying to update snapshot creation timestamp", snapshotKey(snapshot)) klog.V(5).Infof("createSnapshot [%s]: trying to update snapshot creation timestamp", snapshotKey(snapshot))
newSnapshot, err = ctrl.updateSnapshotStatus(snapshot, readyToUse, timestamp, size, false) newSnapshot, err = ctrl.updateSnapshotStatus(snapshot, readyToUse, creationTime, size, false)
if err == nil { if err == nil {
break break
} }
@@ -651,6 +667,7 @@ func (ctrl *csiSnapshotController) createSnapshotOperation(snapshot *crdv1.Volum
class.DeletionPolicy = new(crdv1.DeletionPolicy) class.DeletionPolicy = new(crdv1.DeletionPolicy)
*class.DeletionPolicy = crdv1.VolumeSnapshotContentDelete *class.DeletionPolicy = crdv1.VolumeSnapshotContentDelete
} }
timestamp := creationTime.UnixNano()
snapshotContent := &crdv1.VolumeSnapshotContent{ snapshotContent := &crdv1.VolumeSnapshotContent{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: contentName, Name: contentName,
@@ -674,7 +691,7 @@ func (ctrl *csiSnapshotController) createSnapshotOperation(snapshot *crdv1.Volum
// Try to create the VolumeSnapshotContent object several times // Try to create the VolumeSnapshotContent object several times
for i := 0; i < ctrl.createSnapshotContentRetryCount; i++ { for i := 0; i < ctrl.createSnapshotContentRetryCount; i++ {
klog.V(5).Infof("createSnapshot [%s]: trying to save volume snapshot content %s", snapshotKey(snapshot), snapshotContent.Name) klog.V(5).Infof("createSnapshot [%s]: trying to save volume snapshot content %s", snapshotKey(snapshot), snapshotContent.Name)
if _, err = ctrl.clientset.VolumesnapshotV1alpha1().VolumeSnapshotContents().Create(snapshotContent); err == nil || apierrs.IsAlreadyExists(err) { if _, err = ctrl.clientset.SnapshotV1alpha1().VolumeSnapshotContents().Create(snapshotContent); err == nil || apierrs.IsAlreadyExists(err) {
// Save succeeded. // Save succeeded.
if err != nil { if err != nil {
klog.V(3).Infof("volume snapshot content %q for snapshot %q already exists, reusing", snapshotContent.Name, snapshotKey(snapshot)) klog.V(3).Infof("volume snapshot content %q for snapshot %q already exists, reusing", snapshotContent.Name, snapshotKey(snapshot))
@@ -741,7 +758,7 @@ func (ctrl *csiSnapshotController) deleteSnapshotContentOperation(content *crdv1
return fmt.Errorf("failed to delete snapshot %#v, err: %v", content.Name, err) return fmt.Errorf("failed to delete snapshot %#v, err: %v", content.Name, err)
} }
err = ctrl.clientset.VolumesnapshotV1alpha1().VolumeSnapshotContents().Delete(content.Name, &metav1.DeleteOptions{}) err = ctrl.clientset.SnapshotV1alpha1().VolumeSnapshotContents().Delete(content.Name, &metav1.DeleteOptions{})
if err != nil { if err != nil {
ctrl.eventRecorder.Event(content, v1.EventTypeWarning, "SnapshotContentObjectDeleteError", "Failed to delete snapshot content API object") ctrl.eventRecorder.Event(content, v1.EventTypeWarning, "SnapshotContentObjectDeleteError", "Failed to delete snapshot content API object")
return fmt.Errorf("failed to delete VolumeSnapshotContent %s from API server: %q", content.Name, err) return fmt.Errorf("failed to delete VolumeSnapshotContent %s from API server: %q", content.Name, err)
@@ -752,7 +769,7 @@ func (ctrl *csiSnapshotController) deleteSnapshotContentOperation(content *crdv1
func (ctrl *csiSnapshotController) bindandUpdateVolumeSnapshot(snapshotContent *crdv1.VolumeSnapshotContent, snapshot *crdv1.VolumeSnapshot) (*crdv1.VolumeSnapshot, error) { func (ctrl *csiSnapshotController) bindandUpdateVolumeSnapshot(snapshotContent *crdv1.VolumeSnapshotContent, snapshot *crdv1.VolumeSnapshot) (*crdv1.VolumeSnapshot, error) {
klog.V(5).Infof("bindandUpdateVolumeSnapshot for snapshot [%s]: snapshotContent [%s]", snapshot.Name, snapshotContent.Name) klog.V(5).Infof("bindandUpdateVolumeSnapshot for snapshot [%s]: snapshotContent [%s]", snapshot.Name, snapshotContent.Name)
snapshotObj, err := ctrl.clientset.VolumesnapshotV1alpha1().VolumeSnapshots(snapshot.Namespace).Get(snapshot.Name, metav1.GetOptions{}) snapshotObj, err := ctrl.clientset.SnapshotV1alpha1().VolumeSnapshots(snapshot.Namespace).Get(snapshot.Name, metav1.GetOptions{})
if err != nil { if err != nil {
return nil, fmt.Errorf("error get snapshot %s from api server: %v", snapshotKey(snapshot), err) return nil, fmt.Errorf("error get snapshot %s from api server: %v", snapshotKey(snapshot), err)
} }
@@ -765,7 +782,7 @@ func (ctrl *csiSnapshotController) bindandUpdateVolumeSnapshot(snapshotContent *
} else { } else {
klog.Infof("bindVolumeSnapshotContentToVolumeSnapshot: before bind VolumeSnapshot %s to volumeSnapshotContent [%s]", snapshot.Name, snapshotContent.Name) klog.Infof("bindVolumeSnapshotContentToVolumeSnapshot: before bind VolumeSnapshot %s to volumeSnapshotContent [%s]", snapshot.Name, snapshotContent.Name)
snapshotCopy.Spec.SnapshotContentName = snapshotContent.Name snapshotCopy.Spec.SnapshotContentName = snapshotContent.Name
updateSnapshot, err := ctrl.clientset.VolumesnapshotV1alpha1().VolumeSnapshots(snapshot.Namespace).Update(snapshotCopy) updateSnapshot, err := ctrl.clientset.SnapshotV1alpha1().VolumeSnapshots(snapshot.Namespace).Update(snapshotCopy)
if err != nil { if err != nil {
klog.Infof("bindVolumeSnapshotContentToVolumeSnapshot: Error binding VolumeSnapshot %s to volumeSnapshotContent [%s]. Error [%#v]", snapshot.Name, snapshotContent.Name, err) klog.Infof("bindVolumeSnapshotContentToVolumeSnapshot: Error binding VolumeSnapshot %s to volumeSnapshotContent [%s]. Error [%#v]", snapshot.Name, snapshotContent.Name, err)
return nil, newControllerUpdateError(snapshotKey(snapshot), err.Error()) return nil, newControllerUpdateError(snapshotKey(snapshot), err.Error())
@@ -791,7 +808,7 @@ func (ctrl *csiSnapshotController) updateSnapshotContentSize(content *crdv1.Volu
} }
contentClone := content.DeepCopy() contentClone := content.DeepCopy()
contentClone.Spec.VolumeSnapshotSource.CSI.RestoreSize = &size contentClone.Spec.VolumeSnapshotSource.CSI.RestoreSize = &size
_, err := ctrl.clientset.VolumesnapshotV1alpha1().VolumeSnapshotContents().Update(contentClone) _, err := ctrl.clientset.SnapshotV1alpha1().VolumeSnapshotContents().Update(contentClone)
if err != nil { if err != nil {
return newControllerUpdateError(content.Name, err.Error()) return newControllerUpdateError(content.Name, err.Error())
} }
@@ -804,12 +821,12 @@ func (ctrl *csiSnapshotController) updateSnapshotContentSize(content *crdv1.Volu
} }
// UpdateSnapshotStatus converts snapshot status to crdv1.VolumeSnapshotCondition // UpdateSnapshotStatus converts snapshot status to crdv1.VolumeSnapshotCondition
func (ctrl *csiSnapshotController) updateSnapshotStatus(snapshot *crdv1.VolumeSnapshot, readyToUse bool, createdAt, size int64, bound bool) (*crdv1.VolumeSnapshot, error) { func (ctrl *csiSnapshotController) updateSnapshotStatus(snapshot *crdv1.VolumeSnapshot, readyToUse bool, createdAt time.Time, size int64, bound bool) (*crdv1.VolumeSnapshot, error) {
klog.V(5).Infof("updating VolumeSnapshot[]%s, readyToUse %v, timestamp %v", snapshotKey(snapshot), readyToUse, createdAt) klog.V(5).Infof("updating VolumeSnapshot[]%s, readyToUse %v, timestamp %v", snapshotKey(snapshot), readyToUse, createdAt)
status := snapshot.Status status := snapshot.Status
change := false change := false
timeAt := &metav1.Time{ timeAt := &metav1.Time{
Time: time.Unix(0, createdAt), Time: createdAt,
} }
snapshotClone := snapshot.DeepCopy() snapshotClone := snapshot.DeepCopy()
@@ -932,7 +949,7 @@ func (ctrl *csiSnapshotController) SetDefaultSnapshotClass(snapshot *crdv1.Volum
klog.V(5).Infof("setDefaultSnapshotClass [%s]: default VolumeSnapshotClassName [%s]", snapshot.Name, defaultClasses[0].Name) klog.V(5).Infof("setDefaultSnapshotClass [%s]: default VolumeSnapshotClassName [%s]", snapshot.Name, defaultClasses[0].Name)
snapshotClone := snapshot.DeepCopy() snapshotClone := snapshot.DeepCopy()
snapshotClone.Spec.VolumeSnapshotClassName = &(defaultClasses[0].Name) snapshotClone.Spec.VolumeSnapshotClassName = &(defaultClasses[0].Name)
newSnapshot, err := ctrl.clientset.VolumesnapshotV1alpha1().VolumeSnapshots(snapshotClone.Namespace).Update(snapshotClone) newSnapshot, err := ctrl.clientset.SnapshotV1alpha1().VolumeSnapshots(snapshotClone.Namespace).Update(snapshotClone)
if err != nil { if err != nil {
klog.V(4).Infof("updating VolumeSnapshot[%s] default class failed %v", snapshotKey(snapshot), err) klog.V(4).Infof("updating VolumeSnapshot[%s] default class failed %v", snapshotKey(snapshot), err)
} }
@@ -999,7 +1016,7 @@ func (ctrl *csiSnapshotController) addContentFinalizer(content *crdv1.VolumeSnap
contentClone := content.DeepCopy() contentClone := content.DeepCopy()
contentClone.ObjectMeta.Finalizers = append(contentClone.ObjectMeta.Finalizers, VolumeSnapshotContentFinalizer) contentClone.ObjectMeta.Finalizers = append(contentClone.ObjectMeta.Finalizers, VolumeSnapshotContentFinalizer)
_, err := ctrl.clientset.VolumesnapshotV1alpha1().VolumeSnapshotContents().Update(contentClone) _, err := ctrl.clientset.SnapshotV1alpha1().VolumeSnapshotContents().Update(contentClone)
if err != nil { if err != nil {
return newControllerUpdateError(content.Name, err.Error()) return newControllerUpdateError(content.Name, err.Error())
} }
@@ -1018,7 +1035,7 @@ func (ctrl *csiSnapshotController) removeContentFinalizer(content *crdv1.VolumeS
contentClone := content.DeepCopy() contentClone := content.DeepCopy()
contentClone.ObjectMeta.Finalizers = slice.RemoveString(contentClone.ObjectMeta.Finalizers, VolumeSnapshotContentFinalizer, nil) contentClone.ObjectMeta.Finalizers = slice.RemoveString(contentClone.ObjectMeta.Finalizers, VolumeSnapshotContentFinalizer, nil)
_, err := ctrl.clientset.VolumesnapshotV1alpha1().VolumeSnapshotContents().Update(contentClone) _, err := ctrl.clientset.SnapshotV1alpha1().VolumeSnapshotContents().Update(contentClone)
if err != nil { if err != nil {
return newControllerUpdateError(content.Name, err.Error()) return newControllerUpdateError(content.Name, err.Error())
} }
@@ -1036,7 +1053,7 @@ func (ctrl *csiSnapshotController) removeContentFinalizer(content *crdv1.VolumeS
func (ctrl *csiSnapshotController) addSnapshotFinalizer(snapshot *crdv1.VolumeSnapshot) error { func (ctrl *csiSnapshotController) addSnapshotFinalizer(snapshot *crdv1.VolumeSnapshot) error {
snapshotClone := snapshot.DeepCopy() snapshotClone := snapshot.DeepCopy()
snapshotClone.ObjectMeta.Finalizers = append(snapshotClone.ObjectMeta.Finalizers, VolumeSnapshotFinalizer) snapshotClone.ObjectMeta.Finalizers = append(snapshotClone.ObjectMeta.Finalizers, VolumeSnapshotFinalizer)
_, err := ctrl.clientset.VolumesnapshotV1alpha1().VolumeSnapshots(snapshotClone.Namespace).Update(snapshotClone) _, err := ctrl.clientset.SnapshotV1alpha1().VolumeSnapshots(snapshotClone.Namespace).Update(snapshotClone)
if err != nil { if err != nil {
return newControllerUpdateError(snapshot.Name, err.Error()) return newControllerUpdateError(snapshot.Name, err.Error())
} }
@@ -1055,7 +1072,7 @@ func (ctrl *csiSnapshotController) removeSnapshotFinalizer(snapshot *crdv1.Volum
snapshotClone := snapshot.DeepCopy() snapshotClone := snapshot.DeepCopy()
snapshotClone.ObjectMeta.Finalizers = slice.RemoveString(snapshotClone.ObjectMeta.Finalizers, VolumeSnapshotFinalizer, nil) snapshotClone.ObjectMeta.Finalizers = slice.RemoveString(snapshotClone.ObjectMeta.Finalizers, VolumeSnapshotFinalizer, nil)
_, err := ctrl.clientset.VolumesnapshotV1alpha1().VolumeSnapshots(snapshotClone.Namespace).Update(snapshotClone) _, err := ctrl.clientset.SnapshotV1alpha1().VolumeSnapshots(snapshotClone.Namespace).Update(snapshotClone)
if err != nil { if err != nil {
return newControllerUpdateError(snapshot.Name, err.Error()) return newControllerUpdateError(snapshot.Name, err.Error())
} }
@@ -1068,3 +1085,113 @@ func (ctrl *csiSnapshotController) removeSnapshotFinalizer(snapshot *crdv1.Volum
klog.V(5).Infof("Removed protection finalizer from volume snapshot %s", snapshotKey(snapshot)) klog.V(5).Infof("Removed protection finalizer from volume snapshot %s", snapshotKey(snapshot))
return nil return nil
} }
// ensureSnapshotSourceFinalizer checks if a Finalizer needs to be added for the snapshot source;
// if true, adds a Finalizer for VolumeSnapshot Source PVC
func (ctrl *csiSnapshotController) ensureSnapshotSourceFinalizer(snapshot *crdv1.VolumeSnapshot) error {
// Get snapshot source which is a PVC
pvc, err := ctrl.getClaimFromVolumeSnapshot(snapshot)
if err != nil {
klog.Infof("cannot get claim from snapshot [%s]: [%v] Claim may be deleted already.", snapshot.Name, err)
return nil
}
// If PVC is not being deleted and PVCFinalizer is not added yet, the PVCFinalizer should be added.
if pvc.ObjectMeta.DeletionTimestamp == nil && !slice.ContainsString(pvc.ObjectMeta.Finalizers, PVCFinalizer, nil) {
// Add the finalizer
pvcClone := pvc.DeepCopy()
pvcClone.ObjectMeta.Finalizers = append(pvcClone.ObjectMeta.Finalizers, PVCFinalizer)
_, err = ctrl.client.CoreV1().PersistentVolumeClaims(pvcClone.Namespace).Update(pvcClone)
if err != nil {
klog.Errorf("cannot add finalizer on claim [%s] for snapshot [%s]: [%v]", pvc.Name, snapshot.Name, err)
return newControllerUpdateError(pvcClone.Name, err.Error())
}
klog.Infof("Added protection finalizer to persistent volume claim %s", pvc.Name)
}
return nil
}
// removeSnapshotSourceFinalizer removes a Finalizer for VolumeSnapshot Source PVC.
func (ctrl *csiSnapshotController) removeSnapshotSourceFinalizer(snapshot *crdv1.VolumeSnapshot) error {
// Get snapshot source which is a PVC
pvc, err := ctrl.getClaimFromVolumeSnapshot(snapshot)
if err != nil {
klog.Infof("cannot get claim from snapshot [%s]: [%v] Claim may be deleted already. No need to remove finalizer on the claim.", snapshot.Name, err)
return nil
}
pvcClone := pvc.DeepCopy()
pvcClone.ObjectMeta.Finalizers = slice.RemoveString(pvcClone.ObjectMeta.Finalizers, PVCFinalizer, nil)
_, err = ctrl.client.CoreV1().PersistentVolumeClaims(pvcClone.Namespace).Update(pvcClone)
if err != nil {
return newControllerUpdateError(pvcClone.Name, err.Error())
}
klog.V(5).Infof("Removed protection finalizer from persistent volume claim %s", pvc.Name)
return nil
}
// isSnapshotSourceBeingUsed checks if a PVC is being used as a source to create a snapshot
func (ctrl *csiSnapshotController) isSnapshotSourceBeingUsed(snapshot *crdv1.VolumeSnapshot) bool {
klog.V(5).Infof("isSnapshotSourceBeingUsed[%s]: started", snapshotKey(snapshot))
// Get snapshot source which is a PVC
pvc, err := ctrl.getClaimFromVolumeSnapshot(snapshot)
if err != nil {
klog.Infof("isSnapshotSourceBeingUsed: cannot to get claim from snapshot: %v", err)
return false
}
// Going through snapshots in the cache (snapshotLister). If a snapshot's PVC source
// is the same as the input snapshot's PVC source and snapshot's ReadyToUse status
// is false, the snapshot is still being created from the PVC and the PVC is in-use.
snapshots, err := ctrl.snapshotLister.VolumeSnapshots(snapshot.Namespace).List(labels.Everything())
if err != nil {
return false
}
for _, snap := range snapshots {
// Skip static bound snapshot without a PVC source
if snap.Spec.Source == nil {
klog.V(4).Infof("Skipping static bound snapshot %s when checking PVC %s/%s", snap.Name, pvc.Namespace, pvc.Name)
continue
}
if pvc.Name == snap.Spec.Source.Name && snap.Status.ReadyToUse == false {
klog.V(2).Infof("Keeping PVC %s/%s, it is used by snapshot %s/%s", pvc.Namespace, pvc.Name, snap.Namespace, snap.Name)
return true
}
}
klog.V(5).Infof("isSnapshotSourceBeingUsed: no snapshot is being created from PVC %s/%s", pvc.Namespace, pvc.Name)
return false
}
// checkandRemoveSnapshotSourceFinalizer checks if the snapshot source finalizer should be removed
// and removed it if needed.
func (ctrl *csiSnapshotController) checkandRemoveSnapshotSourceFinalizer(snapshot *crdv1.VolumeSnapshot) error {
// Get snapshot source which is a PVC
pvc, err := ctrl.getClaimFromVolumeSnapshot(snapshot)
if err != nil {
klog.Infof("cannot get claim from snapshot [%s]: [%v] Claim may be deleted already. No need to remove finalizer on the claim.", snapshot.Name, err)
return nil
}
klog.V(5).Infof("checkandRemoveSnapshotSourceFinalizer for snapshot [%s]: snapshot status [%#v]", snapshot.Name, snapshot.Status)
// Check if there is a Finalizer on PVC to be removed
if slice.ContainsString(pvc.ObjectMeta.Finalizers, PVCFinalizer, nil) {
// There is a Finalizer on PVC. Check if PVC is used
// and remove finalizer if it's not used.
isUsed := ctrl.isSnapshotSourceBeingUsed(snapshot)
if !isUsed {
klog.Infof("checkandRemoveSnapshotSourceFinalizer[%s]: Remove Finalizer for PVC %s as it is not used by snapshots in creation", snapshot.Name, pvc.Name)
err = ctrl.removeSnapshotSourceFinalizer(snapshot)
if err != nil {
klog.Errorf("checkandRemoveSnapshotSourceFinalizer [%s]: removeSnapshotSourceFinalizer failed to remove finalizer %v", snapshot.Name, err)
return err
}
}
}
return nil
}

View File

@@ -27,10 +27,11 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
var timeNow = time.Now().UnixNano() var timeNow = time.Now()
var timeNowStamp = timeNow.UnixNano()
var metaTimeNowUnix = &metav1.Time{ var metaTimeNowUnix = &metav1.Time{
Time: time.Unix(0, timeNow), Time: timeNow,
} }
var defaultSize int64 = 1000 var defaultSize int64 = 1000
@@ -68,7 +69,7 @@ func TestCreateSnapshotSync(t *testing.T) {
{ {
name: "6-1 - successful create snapshot with snapshot class gold", name: "6-1 - successful create snapshot with snapshot class gold",
initialContents: nocontents, initialContents: nocontents,
expectedContents: newContentArray("snapcontent-snapuid6-1", classGold, "sid6-1", "pv-uid6-1", "volume6-1", "snapuid6-1", "snap6-1", &deletePolicy, &defaultSize, &timeNow, false), expectedContents: newContentArray("snapcontent-snapuid6-1", classGold, "sid6-1", "pv-uid6-1", "volume6-1", "snapuid6-1", "snap6-1", &deletePolicy, &defaultSize, &timeNowStamp, false),
initialSnapshots: newSnapshotArray("snap6-1", classGold, "", "snapuid6-1", "claim6-1", false, nil, nil, nil), initialSnapshots: newSnapshotArray("snap6-1", classGold, "", "snapuid6-1", "claim6-1", false, nil, nil, nil),
expectedSnapshots: newSnapshotArray("snap6-1", classGold, "snapcontent-snapuid6-1", "snapuid6-1", "claim6-1", false, nil, metaTimeNowUnix, getSize(defaultSize)), expectedSnapshots: newSnapshotArray("snap6-1", classGold, "snapcontent-snapuid6-1", "snapuid6-1", "claim6-1", false, nil, metaTimeNowUnix, getSize(defaultSize)),
initialClaims: newClaimArray("claim6-1", "pvc-uid6-1", "1Gi", "volume6-1", v1.ClaimBound, &classEmpty), initialClaims: newClaimArray("claim6-1", "pvc-uid6-1", "1Gi", "volume6-1", v1.ClaimBound, &classEmpty),
@@ -79,11 +80,11 @@ func TestCreateSnapshotSync(t *testing.T) {
volume: newVolume("volume6-1", "pv-uid6-1", "pv-handle6-1", "1Gi", "pvc-uid6-1", "claim6-1", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty), volume: newVolume("volume6-1", "pv-uid6-1", "pv-handle6-1", "1Gi", "pvc-uid6-1", "claim6-1", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
parameters: map[string]string{"param1": "value1"}, parameters: map[string]string{"param1": "value1"},
// information to return // information to return
driverName: mockDriverName, driverName: mockDriverName,
size: defaultSize, size: defaultSize,
snapshotId: "sid6-1", snapshotId: "sid6-1",
timestamp: timeNow, creationTime: timeNow,
readyToUse: true, readyToUse: true,
}, },
}, },
errors: noerrors, errors: noerrors,
@@ -92,7 +93,7 @@ func TestCreateSnapshotSync(t *testing.T) {
{ {
name: "6-2 - successful create snapshot with snapshot class silver", name: "6-2 - successful create snapshot with snapshot class silver",
initialContents: nocontents, initialContents: nocontents,
expectedContents: newContentArray("snapcontent-snapuid6-2", classSilver, "sid6-2", "pv-uid6-2", "volume6-2", "snapuid6-2", "snap6-2", &deletePolicy, &defaultSize, &timeNow, false), expectedContents: newContentArray("snapcontent-snapuid6-2", classSilver, "sid6-2", "pv-uid6-2", "volume6-2", "snapuid6-2", "snap6-2", &deletePolicy, &defaultSize, &timeNowStamp, false),
initialSnapshots: newSnapshotArray("snap6-2", classSilver, "", "snapuid6-2", "claim6-2", false, nil, nil, nil), initialSnapshots: newSnapshotArray("snap6-2", classSilver, "", "snapuid6-2", "claim6-2", false, nil, nil, nil),
expectedSnapshots: newSnapshotArray("snap6-2", classSilver, "snapcontent-snapuid6-2", "snapuid6-2", "claim6-2", false, nil, metaTimeNowUnix, getSize(defaultSize)), expectedSnapshots: newSnapshotArray("snap6-2", classSilver, "snapcontent-snapuid6-2", "snapuid6-2", "claim6-2", false, nil, metaTimeNowUnix, getSize(defaultSize)),
initialClaims: newClaimArray("claim6-2", "pvc-uid6-2", "1Gi", "volume6-2", v1.ClaimBound, &classEmpty), initialClaims: newClaimArray("claim6-2", "pvc-uid6-2", "1Gi", "volume6-2", v1.ClaimBound, &classEmpty),
@@ -103,11 +104,11 @@ func TestCreateSnapshotSync(t *testing.T) {
volume: newVolume("volume6-2", "pv-uid6-2", "pv-handle6-2", "1Gi", "pvc-uid6-2", "claim6-2", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty), volume: newVolume("volume6-2", "pv-uid6-2", "pv-handle6-2", "1Gi", "pvc-uid6-2", "claim6-2", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
parameters: map[string]string{"param2": "value2"}, parameters: map[string]string{"param2": "value2"},
// information to return // information to return
driverName: mockDriverName, driverName: mockDriverName,
size: defaultSize, size: defaultSize,
snapshotId: "sid6-2", snapshotId: "sid6-2",
timestamp: timeNow, creationTime: timeNow,
readyToUse: true, readyToUse: true,
}, },
}, },
errors: noerrors, errors: noerrors,
@@ -116,7 +117,7 @@ func TestCreateSnapshotSync(t *testing.T) {
{ {
name: "6-3 - successful create snapshot with snapshot class valid-secret-class", name: "6-3 - successful create snapshot with snapshot class valid-secret-class",
initialContents: nocontents, initialContents: nocontents,
expectedContents: newContentArray("snapcontent-snapuid6-3", validSecretClass, "sid6-3", "pv-uid6-3", "volume6-3", "snapuid6-3", "snap6-3", &deletePolicy, &defaultSize, &timeNow, false), expectedContents: newContentArray("snapcontent-snapuid6-3", validSecretClass, "sid6-3", "pv-uid6-3", "volume6-3", "snapuid6-3", "snap6-3", &deletePolicy, &defaultSize, &timeNowStamp, false),
initialSnapshots: newSnapshotArray("snap6-3", validSecretClass, "", "snapuid6-3", "claim6-3", false, nil, nil, nil), initialSnapshots: newSnapshotArray("snap6-3", validSecretClass, "", "snapuid6-3", "claim6-3", false, nil, nil, nil),
expectedSnapshots: newSnapshotArray("snap6-3", validSecretClass, "snapcontent-snapuid6-3", "snapuid6-3", "claim6-3", false, nil, metaTimeNowUnix, getSize(defaultSize)), expectedSnapshots: newSnapshotArray("snap6-3", validSecretClass, "snapcontent-snapuid6-3", "snapuid6-3", "claim6-3", false, nil, metaTimeNowUnix, getSize(defaultSize)),
initialClaims: newClaimArray("claim6-3", "pvc-uid6-3", "1Gi", "volume6-3", v1.ClaimBound, &classEmpty), initialClaims: newClaimArray("claim6-3", "pvc-uid6-3", "1Gi", "volume6-3", v1.ClaimBound, &classEmpty),
@@ -129,11 +130,11 @@ func TestCreateSnapshotSync(t *testing.T) {
parameters: class5Parameters, parameters: class5Parameters,
secrets: map[string]string{"foo": "bar"}, secrets: map[string]string{"foo": "bar"},
// information to return // information to return
driverName: mockDriverName, driverName: mockDriverName,
size: defaultSize, size: defaultSize,
snapshotId: "sid6-3", snapshotId: "sid6-3",
timestamp: timeNow, creationTime: timeNow,
readyToUse: true, readyToUse: true,
}, },
}, },
errors: noerrors, errors: noerrors,
@@ -142,7 +143,7 @@ func TestCreateSnapshotSync(t *testing.T) {
{ {
name: "6-4 - successful create snapshot with snapshot class empty-secret-class", name: "6-4 - successful create snapshot with snapshot class empty-secret-class",
initialContents: nocontents, initialContents: nocontents,
expectedContents: newContentArray("snapcontent-snapuid6-4", emptySecretClass, "sid6-4", "pv-uid6-4", "volume6-4", "snapuid6-4", "snap6-4", &deletePolicy, &defaultSize, &timeNow, false), expectedContents: newContentArray("snapcontent-snapuid6-4", emptySecretClass, "sid6-4", "pv-uid6-4", "volume6-4", "snapuid6-4", "snap6-4", &deletePolicy, &defaultSize, &timeNowStamp, false),
initialSnapshots: newSnapshotArray("snap6-4", emptySecretClass, "", "snapuid6-4", "claim6-4", false, nil, nil, nil), initialSnapshots: newSnapshotArray("snap6-4", emptySecretClass, "", "snapuid6-4", "claim6-4", false, nil, nil, nil),
expectedSnapshots: newSnapshotArray("snap6-4", emptySecretClass, "snapcontent-snapuid6-4", "snapuid6-4", "claim6-4", false, nil, metaTimeNowUnix, getSize(defaultSize)), expectedSnapshots: newSnapshotArray("snap6-4", emptySecretClass, "snapcontent-snapuid6-4", "snapuid6-4", "claim6-4", false, nil, metaTimeNowUnix, getSize(defaultSize)),
initialClaims: newClaimArray("claim6-4", "pvc-uid6-4", "1Gi", "volume6-4", v1.ClaimBound, &classEmpty), initialClaims: newClaimArray("claim6-4", "pvc-uid6-4", "1Gi", "volume6-4", v1.ClaimBound, &classEmpty),
@@ -155,11 +156,11 @@ func TestCreateSnapshotSync(t *testing.T) {
parameters: class4Parameters, parameters: class4Parameters,
secrets: map[string]string{}, secrets: map[string]string{},
// information to return // information to return
driverName: mockDriverName, driverName: mockDriverName,
size: defaultSize, size: defaultSize,
snapshotId: "sid6-4", snapshotId: "sid6-4",
timestamp: timeNow, creationTime: timeNow,
readyToUse: true, readyToUse: true,
}, },
}, },
errors: noerrors, errors: noerrors,
@@ -168,7 +169,7 @@ func TestCreateSnapshotSync(t *testing.T) {
{ {
name: "6-5 - successful create snapshot with status uploading", name: "6-5 - successful create snapshot with status uploading",
initialContents: nocontents, initialContents: nocontents,
expectedContents: newContentArray("snapcontent-snapuid6-5", classGold, "sid6-5", "pv-uid6-5", "volume6-5", "snapuid6-5", "snap6-5", &deletePolicy, &defaultSize, &timeNow, false), expectedContents: newContentArray("snapcontent-snapuid6-5", classGold, "sid6-5", "pv-uid6-5", "volume6-5", "snapuid6-5", "snap6-5", &deletePolicy, &defaultSize, &timeNowStamp, false),
initialSnapshots: newSnapshotArray("snap6-5", classGold, "", "snapuid6-5", "claim6-5", false, nil, nil, nil), initialSnapshots: newSnapshotArray("snap6-5", classGold, "", "snapuid6-5", "claim6-5", false, nil, nil, nil),
expectedSnapshots: newSnapshotArray("snap6-5", classGold, "snapcontent-snapuid6-5", "snapuid6-5", "claim6-5", false, nil, metaTimeNowUnix, getSize(defaultSize)), expectedSnapshots: newSnapshotArray("snap6-5", classGold, "snapcontent-snapuid6-5", "snapuid6-5", "claim6-5", false, nil, metaTimeNowUnix, getSize(defaultSize)),
initialClaims: newClaimArray("claim6-5", "pvc-uid6-5", "1Gi", "volume6-5", v1.ClaimBound, &classEmpty), initialClaims: newClaimArray("claim6-5", "pvc-uid6-5", "1Gi", "volume6-5", v1.ClaimBound, &classEmpty),
@@ -179,11 +180,11 @@ func TestCreateSnapshotSync(t *testing.T) {
volume: newVolume("volume6-5", "pv-uid6-5", "pv-handle6-5", "1Gi", "pvc-uid6-5", "claim6-5", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty), volume: newVolume("volume6-5", "pv-uid6-5", "pv-handle6-5", "1Gi", "pvc-uid6-5", "claim6-5", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
parameters: map[string]string{"param1": "value1"}, parameters: map[string]string{"param1": "value1"},
// information to return // information to return
driverName: mockDriverName, driverName: mockDriverName,
size: defaultSize, size: defaultSize,
snapshotId: "sid6-5", snapshotId: "sid6-5",
timestamp: timeNow, creationTime: timeNow,
readyToUse: true, readyToUse: true,
}, },
}, },
errors: noerrors, errors: noerrors,
@@ -192,7 +193,7 @@ func TestCreateSnapshotSync(t *testing.T) {
{ {
name: "6-6 - successful create snapshot with status error uploading", name: "6-6 - successful create snapshot with status error uploading",
initialContents: nocontents, initialContents: nocontents,
expectedContents: newContentArray("snapcontent-snapuid6-6", classGold, "sid6-6", "pv-uid6-6", "volume6-6", "snapuid6-6", "snap6-6", &deletePolicy, &defaultSize, &timeNow, false), expectedContents: newContentArray("snapcontent-snapuid6-6", classGold, "sid6-6", "pv-uid6-6", "volume6-6", "snapuid6-6", "snap6-6", &deletePolicy, &defaultSize, &timeNowStamp, false),
initialSnapshots: newSnapshotArray("snap6-6", classGold, "", "snapuid6-6", "claim6-6", false, nil, nil, nil), initialSnapshots: newSnapshotArray("snap6-6", classGold, "", "snapuid6-6", "claim6-6", false, nil, nil, nil),
expectedSnapshots: newSnapshotArray("snap6-6", classGold, "snapcontent-snapuid6-6", "snapuid6-6", "claim6-6", false, nil, metaTimeNowUnix, getSize(defaultSize)), expectedSnapshots: newSnapshotArray("snap6-6", classGold, "snapcontent-snapuid6-6", "snapuid6-6", "claim6-6", false, nil, metaTimeNowUnix, getSize(defaultSize)),
initialClaims: newClaimArray("claim6-6", "pvc-uid6-6", "1Gi", "volume6-6", v1.ClaimBound, &classEmpty), initialClaims: newClaimArray("claim6-6", "pvc-uid6-6", "1Gi", "volume6-6", v1.ClaimBound, &classEmpty),
@@ -203,11 +204,11 @@ func TestCreateSnapshotSync(t *testing.T) {
volume: newVolume("volume6-6", "pv-uid6-6", "pv-handle6-6", "1Gi", "pvc-uid6-6", "claim6-6", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty), volume: newVolume("volume6-6", "pv-uid6-6", "pv-handle6-6", "1Gi", "pvc-uid6-6", "claim6-6", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
parameters: map[string]string{"param1": "value1"}, parameters: map[string]string{"param1": "value1"},
// information to return // information to return
driverName: mockDriverName, driverName: mockDriverName,
size: defaultSize, size: defaultSize,
snapshotId: "sid6-6", snapshotId: "sid6-6",
timestamp: timeNow, creationTime: timeNow,
readyToUse: true, readyToUse: true,
}, },
}, },
errors: noerrors, errors: noerrors,
@@ -318,11 +319,11 @@ func TestCreateSnapshotSync(t *testing.T) {
volume: newVolume("volume7-8", "pv-uid7-8", "pv-handle7-8", "1Gi", "pvc-uid7-8", "claim7-8", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty), volume: newVolume("volume7-8", "pv-uid7-8", "pv-handle7-8", "1Gi", "pvc-uid7-8", "claim7-8", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
parameters: map[string]string{"param1": "value1"}, parameters: map[string]string{"param1": "value1"},
// information to return // information to return
driverName: mockDriverName, driverName: mockDriverName,
size: defaultSize, size: defaultSize,
snapshotId: "sid7-8", snapshotId: "sid7-8",
timestamp: timeNow, creationTime: timeNow,
readyToUse: true, readyToUse: true,
}, },
}, },
errors: []reactorError{ errors: []reactorError{
@@ -349,11 +350,11 @@ func TestCreateSnapshotSync(t *testing.T) {
volume: newVolume("volume7-9", "pv-uid7-9", "pv-handle7-9", "1Gi", "pvc-uid7-9", "claim7-9", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty), volume: newVolume("volume7-9", "pv-uid7-9", "pv-handle7-9", "1Gi", "pvc-uid7-9", "claim7-9", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classEmpty),
parameters: map[string]string{"param1": "value1"}, parameters: map[string]string{"param1": "value1"},
// information to return // information to return
driverName: mockDriverName, driverName: mockDriverName,
size: defaultSize, size: defaultSize,
snapshotId: "sid7-9", snapshotId: "sid7-9",
timestamp: timeNow, creationTime: timeNow,
readyToUse: true, readyToUse: true,
}, },
}, },
errors: []reactorError{ errors: []reactorError{

View File

@@ -0,0 +1,67 @@
/*
Copyright 2019 The Kubernetes 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 controller
import (
"testing"
"k8s.io/api/core/v1"
)
// Test single call to ensureSnapshotSourceFinalizer and checkandRemoveSnapshotSourceFinalizer,
// expecting PVCFinalizer to be added or removed
func TestPVCFinalizer(t *testing.T) {
tests := []controllerTest{
{
name: "1-1 - successful add PVC finalizer",
initialSnapshots: newSnapshotArray("snap6-2", classSilver, "", "snapuid6-2", "claim6-2", false, nil, nil, nil),
initialClaims: newClaimArray("claim6-2", "pvc-uid6-2", "1Gi", "volume6-2", v1.ClaimBound, &classEmpty),
test: testAddPVCFinalizer,
expectSuccess: true,
},
{
name: "1-2 - won't add PVC finalizer; already added",
initialSnapshots: newSnapshotArray("snap6-2", classSilver, "", "snapuid6-2", "claim6-2", false, nil, nil, nil),
initialClaims: newClaimArrayFinalizer("claim6-2", "pvc-uid6-2", "1Gi", "volume6-2", v1.ClaimBound, &classEmpty),
test: testAddPVCFinalizer,
expectSuccess: false,
},
{
name: "1-3 - successful remove PVC finalizer",
initialSnapshots: newSnapshotArray("snap6-2", classSilver, "", "snapuid6-2", "claim6-2", false, nil, nil, nil),
initialClaims: newClaimArrayFinalizer("claim6-2", "pvc-uid6-2", "1Gi", "volume6-2", v1.ClaimBound, &classEmpty),
test: testRemovePVCFinalizer,
expectSuccess: true,
},
{
name: "1-4 - won't remove PVC finalizer; already removed",
initialSnapshots: newSnapshotArray("snap6-2", classSilver, "", "snapuid6-2", "claim6-2", false, nil, nil, nil),
initialClaims: newClaimArray("claim6-2", "pvc-uid6-2", "1Gi", "volume6-2", v1.ClaimBound, &classEmpty),
test: testRemovePVCFinalizer,
expectSuccess: false,
},
{
name: "1-5 - won't remove PVC finalizer; PVC in-use",
initialSnapshots: newSnapshotArray("snap6-2", classSilver, "", "snapuid6-2", "claim6-2", false, nil, nil, nil),
initialClaims: newClaimArray("claim6-2", "pvc-uid6-2", "1Gi", "volume6-2", v1.ClaimBound, &classEmpty),
test: testRemovePVCFinalizer,
expectSuccess: false,
},
}
runPVCFinalizerTests(t, tests, snapshotClasses)
}

View File

@@ -79,10 +79,10 @@ func TestSync(t *testing.T) {
parameters: class5Parameters, parameters: class5Parameters,
secrets: map[string]string{"foo": "bar"}, secrets: map[string]string{"foo": "bar"},
// information to return // information to return
driverName: mockDriverName, driverName: mockDriverName,
snapshotId: "sid2-3", snapshotId: "sid2-3",
timestamp: timeNow, creationTime: timeNow,
readyToUse: false, readyToUse: false,
}, },
}, },
errors: noerrors, errors: noerrors,
@@ -114,10 +114,10 @@ func TestSync(t *testing.T) {
parameters: class5Parameters, parameters: class5Parameters,
secrets: map[string]string{"foo": "bar"}, secrets: map[string]string{"foo": "bar"},
// information to return // information to return
driverName: mockDriverName, driverName: mockDriverName,
snapshotId: "sid2-5", snapshotId: "sid2-5",
timestamp: timeNow, creationTime: timeNow,
readyToUse: true, readyToUse: true,
}, },
}, },
errors: noerrors, errors: noerrors,
@@ -125,8 +125,8 @@ func TestSync(t *testing.T) {
}, },
{ {
name: "2-6 - snapshot bound to prebound content correctly, status ready false -> true, ref.UID '' -> 'snapuid2-6'", name: "2-6 - snapshot bound to prebound content correctly, status ready false -> true, ref.UID '' -> 'snapuid2-6'",
initialContents: newContentArray("content2-6", validSecretClass, "sid2-6", noVolume, noVolume, noBoundUID, "snap2-6", &deletePolicy, nil, &timeNow, false), initialContents: newContentArray("content2-6", validSecretClass, "sid2-6", noVolume, noVolume, noBoundUID, "snap2-6", &deletePolicy, nil, &timeNowStamp, false),
expectedContents: newContentArray("content2-6", validSecretClass, "sid2-6", noVolume, noVolume, "snapuid2-6", "snap2-6", &deletePolicy, nil, &timeNow, false), expectedContents: newContentArray("content2-6", validSecretClass, "sid2-6", noVolume, noVolume, "snapuid2-6", "snap2-6", &deletePolicy, nil, &timeNowStamp, false),
initialSnapshots: newSnapshotArray("snap2-6", validSecretClass, "content2-6", "snapuid2-6", noClaim, false, nil, metaTimeNow, nil), initialSnapshots: newSnapshotArray("snap2-6", validSecretClass, "content2-6", "snapuid2-6", noClaim, false, nil, metaTimeNow, nil),
expectedSnapshots: newSnapshotArray("snap2-6", validSecretClass, "content2-6", "snapuid2-6", noClaim, true, nil, metaTimeNow, nil), expectedSnapshots: newSnapshotArray("snap2-6", validSecretClass, "content2-6", "snapuid2-6", noClaim, true, nil, metaTimeNow, nil),
expectedListCalls: []listCall{ expectedListCalls: []listCall{
@@ -178,11 +178,11 @@ func TestSync(t *testing.T) {
parameters: class5Parameters, parameters: class5Parameters,
secrets: map[string]string{"foo": "bar"}, secrets: map[string]string{"foo": "bar"},
// information to return // information to return
driverName: mockDriverName, driverName: mockDriverName,
size: defaultSize, size: defaultSize,
snapshotId: "sid2-8", snapshotId: "sid2-8",
timestamp: timeNow, creationTime: timeNow,
readyToUse: true, readyToUse: true,
}, },
}, },
errors: []reactorError{ errors: []reactorError{

View File

@@ -75,6 +75,9 @@ var snapshotterSecretParams = deprecatedSecretParamsMap{
secretNamespaceKey: prefixedSnapshotterSecretNamespaceKey, secretNamespaceKey: prefixedSnapshotterSecretNamespaceKey,
} }
// Name of finalizer on PVCs that have been used as a source to create VolumeSnapshots
const PVCFinalizer = "snapshot.storage.kubernetes.io/pvc-protection"
func snapshotKey(vs *crdv1.VolumeSnapshot) string { func snapshotKey(vs *crdv1.VolumeSnapshot) string {
return fmt.Sprintf("%s/%s", vs.Namespace, vs.Name) return fmt.Sprintf("%s/%s", vs.Namespace, vs.Name)
} }

View File

@@ -19,10 +19,10 @@ package snapshotter
import ( import (
"context" "context"
"fmt" "fmt"
"time"
"github.com/container-storage-interface/spec/lib/go/csi" "github.com/container-storage-interface/spec/lib/go/csi"
"github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/timestamp"
csirpc "github.com/kubernetes-csi/csi-lib-utils/rpc" csirpc "github.com/kubernetes-csi/csi-lib-utils/rpc"
"google.golang.org/grpc" "google.golang.org/grpc"
@@ -34,13 +34,13 @@ import (
// Snapshotter implements CreateSnapshot/DeleteSnapshot operations against a remote CSI driver. // Snapshotter implements CreateSnapshot/DeleteSnapshot operations against a remote CSI driver.
type Snapshotter interface { type Snapshotter interface {
// CreateSnapshot creates a snapshot for a volume // CreateSnapshot creates a snapshot for a volume
CreateSnapshot(ctx context.Context, snapshotName string, volume *v1.PersistentVolume, parameters map[string]string, snapshotterCredentials map[string]string) (driverName string, snapshotId string, timestamp int64, size int64, readyToUse bool, err error) CreateSnapshot(ctx context.Context, snapshotName string, volume *v1.PersistentVolume, parameters map[string]string, snapshotterCredentials map[string]string) (driverName string, snapshotId string, timestamp time.Time, size int64, readyToUse bool, err error)
// DeleteSnapshot deletes a snapshot from a volume // DeleteSnapshot deletes a snapshot from a volume
DeleteSnapshot(ctx context.Context, snapshotID string, snapshotterCredentials map[string]string) (err error) DeleteSnapshot(ctx context.Context, snapshotID string, snapshotterCredentials map[string]string) (err error)
// GetSnapshotStatus returns if a snapshot is ready to use, creation time, and restore size. // GetSnapshotStatus returns if a snapshot is ready to use, creation time, and restore size.
GetSnapshotStatus(ctx context.Context, snapshotID string) (bool, int64, int64, error) GetSnapshotStatus(ctx context.Context, snapshotID string) (bool, time.Time, int64, error)
} }
type snapshot struct { type snapshot struct {
@@ -53,17 +53,17 @@ func NewSnapshotter(conn *grpc.ClientConn) Snapshotter {
} }
} }
func (s *snapshot) CreateSnapshot(ctx context.Context, snapshotName string, volume *v1.PersistentVolume, parameters map[string]string, snapshotterCredentials map[string]string) (string, string, int64, int64, bool, error) { func (s *snapshot) CreateSnapshot(ctx context.Context, snapshotName string, volume *v1.PersistentVolume, parameters map[string]string, snapshotterCredentials map[string]string) (string, string, time.Time, int64, bool, error) {
klog.V(5).Infof("CSI CreateSnapshot: %s", snapshotName) klog.V(5).Infof("CSI CreateSnapshot: %s", snapshotName)
if volume.Spec.CSI == nil { if volume.Spec.CSI == nil {
return "", "", 0, 0, false, fmt.Errorf("CSIPersistentVolumeSource not defined in spec") return "", "", time.Time{}, 0, false, fmt.Errorf("CSIPersistentVolumeSource not defined in spec")
} }
client := csi.NewControllerClient(s.conn) client := csi.NewControllerClient(s.conn)
driverName, err := csirpc.GetDriverName(ctx, s.conn) driverName, err := csirpc.GetDriverName(ctx, s.conn)
if err != nil { if err != nil {
return "", "", 0, 0, false, err return "", "", time.Time{}, 0, false, err
} }
req := csi.CreateSnapshotRequest{ req := csi.CreateSnapshotRequest{
@@ -75,13 +75,13 @@ func (s *snapshot) CreateSnapshot(ctx context.Context, snapshotName string, volu
rsp, err := client.CreateSnapshot(ctx, &req) rsp, err := client.CreateSnapshot(ctx, &req)
if err != nil { if err != nil {
return "", "", 0, 0, false, err return "", "", time.Time{}, 0, false, err
} }
klog.V(5).Infof("CSI CreateSnapshot: %s driver name [%s] snapshot ID [%s] time stamp [%d] size [%d] readyToUse [%v]", snapshotName, driverName, rsp.Snapshot.SnapshotId, rsp.Snapshot.CreationTime, rsp.Snapshot.SizeBytes, rsp.Snapshot.ReadyToUse) klog.V(5).Infof("CSI CreateSnapshot: %s driver name [%s] snapshot ID [%s] time stamp [%d] size [%d] readyToUse [%v]", snapshotName, driverName, rsp.Snapshot.SnapshotId, rsp.Snapshot.CreationTime, rsp.Snapshot.SizeBytes, rsp.Snapshot.ReadyToUse)
creationTime, err := timestampToUnixTime(rsp.Snapshot.CreationTime) creationTime, err := ptypes.Timestamp(rsp.Snapshot.CreationTime)
if err != nil { if err != nil {
return "", "", 0, 0, false, err return "", "", time.Time{}, 0, false, err
} }
return driverName, rsp.Snapshot.SnapshotId, creationTime, rsp.Snapshot.SizeBytes, rsp.Snapshot.ReadyToUse, nil return driverName, rsp.Snapshot.SnapshotId, creationTime, rsp.Snapshot.SizeBytes, rsp.Snapshot.ReadyToUse, nil
} }
@@ -101,7 +101,7 @@ func (s *snapshot) DeleteSnapshot(ctx context.Context, snapshotID string, snapsh
return nil return nil
} }
func (s *snapshot) GetSnapshotStatus(ctx context.Context, snapshotID string) (bool, int64, int64, error) { func (s *snapshot) GetSnapshotStatus(ctx context.Context, snapshotID string) (bool, time.Time, int64, error) {
client := csi.NewControllerClient(s.conn) client := csi.NewControllerClient(s.conn)
req := csi.ListSnapshotsRequest{ req := csi.ListSnapshotsRequest{
@@ -110,26 +110,16 @@ func (s *snapshot) GetSnapshotStatus(ctx context.Context, snapshotID string) (bo
rsp, err := client.ListSnapshots(ctx, &req) rsp, err := client.ListSnapshots(ctx, &req)
if err != nil { if err != nil {
return false, 0, 0, err return false, time.Time{}, 0, err
} }
if rsp.Entries == nil || len(rsp.Entries) == 0 { if rsp.Entries == nil || len(rsp.Entries) == 0 {
return false, 0, 0, fmt.Errorf("can not find snapshot for snapshotID %s", snapshotID) return false, time.Time{}, 0, fmt.Errorf("can not find snapshot for snapshotID %s", snapshotID)
} }
creationTime, err := timestampToUnixTime(rsp.Entries[0].Snapshot.CreationTime) creationTime, err := ptypes.Timestamp(rsp.Entries[0].Snapshot.CreationTime)
if err != nil { if err != nil {
return false, 0, 0, err return false, time.Time{}, 0, err
} }
return rsp.Entries[0].Snapshot.ReadyToUse, creationTime, rsp.Entries[0].Snapshot.SizeBytes, nil return rsp.Entries[0].Snapshot.ReadyToUse, creationTime, rsp.Entries[0].Snapshot.SizeBytes, nil
} }
func timestampToUnixTime(t *timestamp.Timestamp) (int64, error) {
time, err := ptypes.Timestamp(t)
if err != nil {
return -1, err
}
// TODO: clean this up, we probably don't need this translation layer
// and can just use time.Time
return time.UnixNano(), nil
}

View File

@@ -21,6 +21,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"testing" "testing"
"time"
"github.com/container-storage-interface/spec/lib/go/csi" "github.com/container-storage-interface/spec/lib/go/csi"
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
@@ -118,7 +119,7 @@ func TestCreateSnapshot(t *testing.T) {
type snapshotResult struct { type snapshotResult struct {
driverName string driverName string
snapshotId string snapshotId string
timestamp int64 timestamp time.Time
size int64 size int64
readyToUse bool readyToUse bool
} }
@@ -127,7 +128,7 @@ func TestCreateSnapshot(t *testing.T) {
size: 1000, size: 1000,
driverName: driverName, driverName: driverName,
snapshotId: defaultID, snapshotId: defaultID,
timestamp: createTime.UnixNano(), timestamp: createTime,
readyToUse: true, readyToUse: true,
} }
@@ -376,7 +377,7 @@ func TestGetSnapshotStatus(t *testing.T) {
injectError codes.Code injectError codes.Code
expectError bool expectError bool
expectReady bool expectReady bool
expectCreateAt int64 expectCreateAt time.Time
expectSize int64 expectSize int64
}{ }{
{ {
@@ -386,7 +387,7 @@ func TestGetSnapshotStatus(t *testing.T) {
output: defaultResponse, output: defaultResponse,
expectError: false, expectError: false,
expectReady: true, expectReady: true,
expectCreateAt: createTime.UnixNano(), expectCreateAt: createTime,
expectSize: size, expectSize: size,
}, },
{ {