diff --git a/pkg/controller/csi_handler.go b/pkg/controller/csi_handler.go index 3b3a9000a..cfc79a15c 100644 --- a/pkg/controller/csi_handler.go +++ b/pkg/controller/csi_handler.go @@ -32,7 +32,7 @@ import ( type Handler interface { 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 - GetSnapshotStatus(content *crdv1.VolumeSnapshotContent) (bool, time.Time, int64, error) + GetSnapshotStatus(content *crdv1.VolumeSnapshotContent, snapshotterCredentials map[string]string) (bool, time.Time, int64, error) } // csiHandler is a handler that calls CSI to create/delete volume snapshot. @@ -89,14 +89,14 @@ func (handler *csiHandler) DeleteSnapshot(content *crdv1.VolumeSnapshotContent, return nil } -func (handler *csiHandler) GetSnapshotStatus(content *crdv1.VolumeSnapshotContent) (bool, time.Time, int64, error) { +func (handler *csiHandler) GetSnapshotStatus(content *crdv1.VolumeSnapshotContent, snapshotterCredentials map[string]string) (bool, time.Time, int64, error) { if content.Spec.CSI == nil { return false, time.Time{}, 0, fmt.Errorf("CSISnapshot not defined in spec") } ctx, cancel := context.WithTimeout(context.Background(), handler.timeout) 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, snapshotterCredentials) if err != nil { return false, time.Time{}, 0, fmt.Errorf("failed to list snapshot content %s: %q", content.Name, err) } diff --git a/pkg/controller/snapshot_controller.go b/pkg/controller/snapshot_controller.go index 5333c63f4..33ec9fcd6 100644 --- a/pkg/controller/snapshot_controller.go +++ b/pkg/controller/snapshot_controller.go @@ -549,7 +549,7 @@ func (ctrl *csiSnapshotController) getCreateSnapshotInput(snapshot *crdv1.Volume contentName := GetSnapshotContentNameForSnapshot(snapshot) // Resolve snapshotting secret credentials. - snapshotterSecretRef, err := getSecretReference(class.Parameters, contentName, snapshot) + snapshotterSecretRef, err := getSecretReference(class.Parameters, snapshotterSecretParams, contentName, snapshot) if err != nil { return nil, nil, "", nil, err } @@ -561,6 +561,22 @@ func (ctrl *csiSnapshotController) getCreateSnapshotInput(snapshot *crdv1.Volume return class, volume, contentName, snapshotterCredentials, nil } +func (ctrl *csiSnapshotController) getListSnapshotCredentials(snapshot *crdv1.VolumeSnapshot) (map[string]string, error) { + className := snapshot.Spec.VolumeSnapshotClassName + if className == nil { + return nil, fmt.Errorf("failed to get list snapshot credentials for %s without a snapshot class", snapshot.Name) + } + vsc, err := ctrl.clientset.SnapshotV1alpha1().VolumeSnapshotClasses().Get(className, metav1.GetOptions{}) + if err != nil { + return nil, fmt.Errorf("failed to get the snapshot class %s: Error: [%#v]", className, err) + } + secretRef, err := getSecretReference(vsc.Parameters, snapshotterListSecretParams, snapshot.Spec.SnapshotContentName) + if err != nil { + return nil, fmt.Errorf("failed to get secret reference for list operation") + } + return getCredentials(ctrl.client, secretRef) +} + func (ctrl *csiSnapshotController) checkandUpdateBoundSnapshotStatusOperation(snapshot *crdv1.VolumeSnapshot, content *crdv1.VolumeSnapshotContent) (*crdv1.VolumeSnapshot, error) { var err error var creationTime time.Time @@ -570,8 +586,13 @@ func (ctrl *csiSnapshotController) checkandUpdateBoundSnapshotStatusOperation(sn var snapshotID string if snapshot.Spec.Source == nil { + snapshotterListCredentials, err := ctrl.getListSnapshotCredentials(snapshot) + if err != nil { + klog.Errorf("checkAndUpdateBoundSnapshotStatusOperation: failed to get list snapshot credentials from snapshot [%s", snapshot.Name) + return nil, err + } klog.V(5).Infof("checkandUpdateBoundSnapshotStatusOperation: checking whether snapshot [%s] is pre-bound to content [%s]", snapshot.Name, content.Name) - readyToUse, creationTime, size, err = ctrl.handler.GetSnapshotStatus(content) + readyToUse, creationTime, size, err = ctrl.handler.GetSnapshotStatus(content, snapshotterListCredentials) if err != nil { klog.Errorf("checkandUpdateBoundSnapshotStatusOperation: failed to call get snapshot status to check whether snapshot is ready to use %q", err) return nil, err @@ -741,7 +762,7 @@ func (ctrl *csiSnapshotController) deleteSnapshotContentOperation(content *crdv1 if snapshotClass, err := ctrl.classLister.Get(*snapshotClassName); err == nil { // Resolve snapshotting secret credentials. // No VolumeSnapshot is provided when resolving delete secret names, since the VolumeSnapshot may or may not exist at delete time. - snapshotterSecretRef, err := getSecretReference(snapshotClass.Parameters, content.Name, nil) + snapshotterSecretRef, err := getSecretReference(snapshotClass.Parameters, snapshotterSecretParams, content.Name, nil) if err != nil { return err } diff --git a/pkg/controller/util.go b/pkg/controller/util.go index b91f32591..a5c7b6d9a 100644 --- a/pkg/controller/util.go +++ b/pkg/controller/util.go @@ -18,7 +18,10 @@ package controller import ( "fmt" + "os" + "strconv" "strings" + "time" crdv1 "github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1" "k8s.io/api/core/v1" @@ -30,9 +33,6 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/klog" "k8s.io/kubernetes/pkg/util/slice" - "os" - "strconv" - "time" ) var ( @@ -57,6 +57,9 @@ const ( prefixedSnapshotterSecretNameKey = csiParameterPrefix + "snapshotter-secret-name" prefixedSnapshotterSecretNamespaceKey = csiParameterPrefix + "snapshotter-secret-namespace" + listSnapshotSecretNameKey = csiParameterPrefix + "snapshotter-list-snapshot-secret-name" + listSnapshotSecretNamespaceKey = csiParameterPrefix + "snapshotter-list-snapshot-secret-namespace" + // [Deprecated] CSI Parameters that are put into fields but // NOT stripped from the parameters passed to CreateSnapshot snapshotterSecretNameKey = "csiSnapshotterSecretName" @@ -68,13 +71,19 @@ const ( ) var snapshotterSecretParams = deprecatedSecretParamsMap{ - name: "Snapshotter", + name: "Snapshotter (CreateSnapshot, DeleteSnapshot)", deprecatedSecretNameKey: snapshotterSecretNameKey, deprecatedSecretNamespaceKey: snapshotterSecretNamespaceKey, secretNameKey: prefixedSnapshotterSecretNameKey, secretNamespaceKey: prefixedSnapshotterSecretNamespaceKey, } +var snapshotterListSecretParams = deprecatedSecretParamsMap{ + name: "Snapshotter (ListSnapshot)", + secretNameKey: listSnapshotSecretNameKey, + secretNamespaceKey: listSnapshotSecretNamespaceKey, +} + // Name of finalizer on PVCs that have been used as a source to create VolumeSnapshots const PVCFinalizer = "snapshot.storage.kubernetes.io/pvc-protection" @@ -227,8 +236,8 @@ func verifyAndGetSecretNameAndNamespaceTemplate(secret deprecatedSecretParamsMap // - the nameTemplate or namespaceTemplate contains a token that cannot be resolved // - the resolved name is not a valid secret name // - the resolved namespace is not a valid namespace name -func getSecretReference(snapshotClassParams map[string]string, snapContentName string, snapshot *crdv1.VolumeSnapshot) (*v1.SecretReference, error) { - nameTemplate, namespaceTemplate, err := verifyAndGetSecretNameAndNamespaceTemplate(snapshotterSecretParams, snapshotClassParams) +func getSecretReference(snapshotClassParams map[string]string, secretMap deprecatedSecretParamsMap, snapContentName string, snapshot *crdv1.VolumeSnapshot) (*v1.SecretReference, error) { + nameTemplate, namespaceTemplate, err := verifyAndGetSecretNameAndNamespaceTemplate(secretMap, snapshotClassParams) if err != nil { return nil, fmt.Errorf("failed to get name and namespace template from params: %v", err) } diff --git a/pkg/snapshotter/snapshotter.go b/pkg/snapshotter/snapshotter.go index 157f08972..b0295bdbb 100644 --- a/pkg/snapshotter/snapshotter.go +++ b/pkg/snapshotter/snapshotter.go @@ -24,9 +24,7 @@ import ( "github.com/container-storage-interface/spec/lib/go/csi" "github.com/golang/protobuf/ptypes" csirpc "github.com/kubernetes-csi/csi-lib-utils/rpc" - "google.golang.org/grpc" - "k8s.io/api/core/v1" "k8s.io/klog" ) @@ -40,7 +38,7 @@ type Snapshotter interface { 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(ctx context.Context, snapshotID string) (bool, time.Time, int64, error) + GetSnapshotStatus(ctx context.Context, snapshotID string, snapshotterCredentials map[string]string) (bool, time.Time, int64, error) } type snapshot struct { @@ -117,7 +115,7 @@ func (s *snapshot) isListSnapshotsSupported(ctx context.Context) (bool, error) { return false, nil } -func (s *snapshot) GetSnapshotStatus(ctx context.Context, snapshotID string) (bool, time.Time, int64, error) { +func (s *snapshot) GetSnapshotStatus(ctx context.Context, snapshotID string, snapshotterCredentials map[string]string) (bool, time.Time, int64, error) { client := csi.NewControllerClient(s.conn) // If the driver does not support ListSnapshots, assume the snapshot ID is valid. @@ -130,6 +128,7 @@ func (s *snapshot) GetSnapshotStatus(ctx context.Context, snapshotID string) (bo } req := csi.ListSnapshotsRequest{ SnapshotId: snapshotID, + Secrets: snapshotterCredentials, } rsp, err := client.ListSnapshots(ctx, &req) if err != nil {