mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-06 10:43:56 +00:00
Merge pull request #80568 from pohly/ephemeral-mode-check
ephemeral mode check
This commit is contained in:
commit
087aafc18d
@ -344,6 +344,7 @@ API rule violation: list_type_missing,k8s.io/api/storage/v1,StorageClassList,Ite
|
|||||||
API rule violation: list_type_missing,k8s.io/api/storage/v1,VolumeAttachmentList,Items
|
API rule violation: list_type_missing,k8s.io/api/storage/v1,VolumeAttachmentList,Items
|
||||||
API rule violation: list_type_missing,k8s.io/api/storage/v1alpha1,VolumeAttachmentList,Items
|
API rule violation: list_type_missing,k8s.io/api/storage/v1alpha1,VolumeAttachmentList,Items
|
||||||
API rule violation: list_type_missing,k8s.io/api/storage/v1beta1,CSIDriverList,Items
|
API rule violation: list_type_missing,k8s.io/api/storage/v1beta1,CSIDriverList,Items
|
||||||
|
API rule violation: list_type_missing,k8s.io/api/storage/v1beta1,CSIDriverSpec,VolumeLifecycleModes
|
||||||
API rule violation: list_type_missing,k8s.io/api/storage/v1beta1,CSINodeDriver,TopologyKeys
|
API rule violation: list_type_missing,k8s.io/api/storage/v1beta1,CSINodeDriver,TopologyKeys
|
||||||
API rule violation: list_type_missing,k8s.io/api/storage/v1beta1,CSINodeList,Items
|
API rule violation: list_type_missing,k8s.io/api/storage/v1beta1,CSINodeList,Items
|
||||||
API rule violation: list_type_missing,k8s.io/api/storage/v1beta1,CSINodeSpec,Drivers
|
API rule violation: list_type_missing,k8s.io/api/storage/v1beta1,CSINodeSpec,Drivers
|
||||||
|
9
api/openapi-spec/swagger.json
generated
9
api/openapi-spec/swagger.json
generated
@ -16766,8 +16766,15 @@
|
|||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"podInfoOnMount": {
|
"podInfoOnMount": {
|
||||||
"description": "If set to true, podInfoOnMount indicates this CSI volume driver requires additional pod information (like podName, podUID, etc.) during mount operations. If set to false, pod information will not be passed on mount. Default is false. The CSI driver specifies podInfoOnMount as part of driver deployment. If true, Kubelet will pass pod information as VolumeContext in the CSI NodePublishVolume() calls. The CSI driver is responsible for parsing and validating the information passed in as VolumeContext. The following VolumeConext will be passed if podInfoOnMount is set to true. This list might grow, but the prefix will be used. \"csi.storage.k8s.io/pod.name\": pod.Name \"csi.storage.k8s.io/pod.namespace\": pod.Namespace \"csi.storage.k8s.io/pod.uid\": string(pod.UID)",
|
"description": "If set to true, podInfoOnMount indicates this CSI volume driver requires additional pod information (like podName, podUID, etc.) during mount operations. If set to false, pod information will not be passed on mount. Default is false. The CSI driver specifies podInfoOnMount as part of driver deployment. If true, Kubelet will pass pod information as VolumeContext in the CSI NodePublishVolume() calls. The CSI driver is responsible for parsing and validating the information passed in as VolumeContext. The following VolumeConext will be passed if podInfoOnMount is set to true. This list might grow, but the prefix will be used. \"csi.storage.k8s.io/pod.name\": pod.Name \"csi.storage.k8s.io/pod.namespace\": pod.Namespace \"csi.storage.k8s.io/pod.uid\": string(pod.UID) \"csi.storage.k8s.io/ephemeral\": \"true\" iff the volume is an ephemeral inline volume\n defined by a CSIVolumeSource, otherwise \"false\"\n\n\"csi.storage.k8s.io/ephemeral\" is a new feature in Kubernetes 1.16. It is only required for drivers which support both the \"Persistent\" and \"Ephemeral\" VolumeLifecycleMode. Other drivers can leave pod info disabled and/or ignore this field. As Kubernetes 1.15 doesn't support this field, drivers can only support one mode when deployed on such a cluster and the deployment determines which mode that is, for example via a command line parameter of the driver.",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"volumeLifecycleModes": {
|
||||||
|
"description": "VolumeLifecycleModes defines what kind of volumes this CSI volume driver supports. The default if the list is empty is \"Persistent\", which is the usage defined by the CSI specification and implemented in Kubernetes via the usual PV/PVC mechanism. The other mode is \"Ephemeral\". In this mode, volumes are defined inline inside the pod spec with CSIVolumeSource and their lifecycle is tied to the lifecycle of that pod. A driver has to be aware of this because it is only going to get a NodePublishVolume call for such a volume. For more information about implementing this mode, see https://kubernetes-csi.github.io/docs/ephemeral-local-volumes.html A driver can support one or more of these modes and more modes may be added in the future.",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package fuzzer
|
package fuzzer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
fuzz "github.com/google/gofuzz"
|
fuzz "github.com/google/gofuzz"
|
||||||
|
|
||||||
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
@ -37,6 +38,37 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
|
|||||||
func(obj *storage.CSIDriver, c fuzz.Continue) {
|
func(obj *storage.CSIDriver, c fuzz.Continue) {
|
||||||
c.FuzzNoCustom(obj) // fuzz self without calling this function again
|
c.FuzzNoCustom(obj) // fuzz self without calling this function again
|
||||||
|
|
||||||
|
// Custom fuzzing for volume modes.
|
||||||
|
switch c.Rand.Intn(7) {
|
||||||
|
case 0:
|
||||||
|
obj.Spec.VolumeLifecycleModes = nil
|
||||||
|
case 1:
|
||||||
|
obj.Spec.VolumeLifecycleModes = []storage.VolumeLifecycleMode{}
|
||||||
|
case 2:
|
||||||
|
// Invalid mode.
|
||||||
|
obj.Spec.VolumeLifecycleModes = []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecycleMode(fmt.Sprintf("%d", c.Rand.Int31())),
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
obj.Spec.VolumeLifecycleModes = []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecyclePersistent,
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
obj.Spec.VolumeLifecycleModes = []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecycleEphemeral,
|
||||||
|
}
|
||||||
|
case 5:
|
||||||
|
obj.Spec.VolumeLifecycleModes = []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecyclePersistent,
|
||||||
|
storage.VolumeLifecycleEphemeral,
|
||||||
|
}
|
||||||
|
case 6:
|
||||||
|
obj.Spec.VolumeLifecycleModes = []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecycleEphemeral,
|
||||||
|
storage.VolumeLifecyclePersistent,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// match defaulting
|
// match defaulting
|
||||||
if obj.Spec.AttachRequired == nil {
|
if obj.Spec.AttachRequired == nil {
|
||||||
obj.Spec.AttachRequired = new(bool)
|
obj.Spec.AttachRequired = new(bool)
|
||||||
@ -46,6 +78,11 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
|
|||||||
obj.Spec.PodInfoOnMount = new(bool)
|
obj.Spec.PodInfoOnMount = new(bool)
|
||||||
*(obj.Spec.PodInfoOnMount) = false
|
*(obj.Spec.PodInfoOnMount) = false
|
||||||
}
|
}
|
||||||
|
if obj.Spec.VolumeLifecycleModes == nil {
|
||||||
|
obj.Spec.VolumeLifecycleModes = []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecyclePersistent,
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,8 +293,47 @@ type CSIDriverSpec struct {
|
|||||||
// "csi.storage.k8s.io/pod.uid": string(pod.UID)
|
// "csi.storage.k8s.io/pod.uid": string(pod.UID)
|
||||||
// +optional
|
// +optional
|
||||||
PodInfoOnMount *bool
|
PodInfoOnMount *bool
|
||||||
|
|
||||||
|
// VolumeLifecycleModes defines what kind of volumes this CSI volume driver supports.
|
||||||
|
// The default if the list is empty is "Persistent", which is the usage
|
||||||
|
// defined by the CSI specification and implemented in Kubernetes via the usual
|
||||||
|
// PV/PVC mechanism.
|
||||||
|
// The other mode is "Ephemeral". In this mode, volumes are defined inline
|
||||||
|
// inside the pod spec with CSIVolumeSource and their lifecycle is tied to
|
||||||
|
// the lifecycle of that pod. A driver has to be aware of this
|
||||||
|
// because it is only going to get a NodePublishVolume call for such a volume.
|
||||||
|
// For more information about implementing this mode, see
|
||||||
|
// https://kubernetes-csi.github.io/docs/ephemeral-local-volumes.html
|
||||||
|
// A driver can support one or more of these mode and
|
||||||
|
// more modes may be added in the future.
|
||||||
|
// +optional
|
||||||
|
VolumeLifecycleModes []VolumeLifecycleMode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VolumeLifecycleMode specifies how a CSI volume is used in Kubernetes.
|
||||||
|
// More modes may be added in the future.
|
||||||
|
type VolumeLifecycleMode string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// VolumeLifecyclePersistent explicitly confirms that the driver implements
|
||||||
|
// the full CSI spec. It is the default when CSIDriverSpec.VolumeLifecycleModes is not
|
||||||
|
// set. Such volumes are managed in Kubernetes via the persistent volume
|
||||||
|
// claim mechanism and have a lifecycle that is independent of the pods which
|
||||||
|
// use them.
|
||||||
|
VolumeLifecyclePersistent VolumeLifecycleMode = "Persistent"
|
||||||
|
// VolumeLifecycleEphemeral indicates that the driver can be used for
|
||||||
|
// ephemeral inline volumes. Such volumes are specified inside the pod
|
||||||
|
// spec with a CSIVolumeSource and, as far as Kubernetes is concerned, have
|
||||||
|
// a lifecycle that is tied to the lifecycle of the pod. For example, such
|
||||||
|
// a volume might contain data that gets created specifically for that pod,
|
||||||
|
// like secrets.
|
||||||
|
// But how the volume actually gets created and managed is entirely up to
|
||||||
|
// the driver. It might also use reference counting to share the same volume
|
||||||
|
// instance among different pods if the CSIVolumeSource of those pods is
|
||||||
|
// identical.
|
||||||
|
VolumeLifecycleEphemeral VolumeLifecycleMode = "Ephemeral"
|
||||||
|
)
|
||||||
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
// CSINode holds information about all CSI drivers installed on a node.
|
// CSINode holds information about all CSI drivers installed on a node.
|
||||||
|
@ -20,11 +20,13 @@ go_library(
|
|||||||
"//pkg/apis/core:go_default_library",
|
"//pkg/apis/core:go_default_library",
|
||||||
"//pkg/apis/core/v1:go_default_library",
|
"//pkg/apis/core/v1:go_default_library",
|
||||||
"//pkg/apis/storage:go_default_library",
|
"//pkg/apis/storage:go_default_library",
|
||||||
|
"//pkg/features:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/api/storage/v1beta1:go_default_library",
|
"//staging/src/k8s.io/api/storage/v1beta1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -51,7 +53,10 @@ go_test(
|
|||||||
deps = [
|
deps = [
|
||||||
"//pkg/api/legacyscheme:go_default_library",
|
"//pkg/api/legacyscheme:go_default_library",
|
||||||
"//pkg/apis/storage/install:go_default_library",
|
"//pkg/apis/storage/install:go_default_library",
|
||||||
|
"//pkg/features:go_default_library",
|
||||||
"//staging/src/k8s.io/api/storage/v1beta1:go_default_library",
|
"//staging/src/k8s.io/api/storage/v1beta1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||||
|
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -20,6 +20,8 @@ import (
|
|||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
)
|
)
|
||||||
|
|
||||||
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
||||||
@ -47,4 +49,7 @@ func SetDefaults_CSIDriver(obj *storagev1beta1.CSIDriver) {
|
|||||||
obj.Spec.PodInfoOnMount = new(bool)
|
obj.Spec.PodInfoOnMount = new(bool)
|
||||||
*(obj.Spec.PodInfoOnMount) = false
|
*(obj.Spec.PodInfoOnMount) = false
|
||||||
}
|
}
|
||||||
|
if len(obj.Spec.VolumeLifecycleModes) == 0 && utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
|
||||||
|
obj.Spec.VolumeLifecycleModes = append(obj.Spec.VolumeLifecycleModes, storagev1beta1.VolumeLifecyclePersistent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,11 @@ import (
|
|||||||
|
|
||||||
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
_ "k8s.io/kubernetes/pkg/apis/storage/install"
|
_ "k8s.io/kubernetes/pkg/apis/storage/install"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
)
|
)
|
||||||
|
|
||||||
func roundTrip(t *testing.T, obj runtime.Object) runtime.Object {
|
func roundTrip(t *testing.T, obj runtime.Object) runtime.Object {
|
||||||
@ -81,3 +84,30 @@ func TestSetDefaultAttachRequired(t *testing.T) {
|
|||||||
t.Errorf("Expected PodInfoOnMount to be defaulted to: %+v, got: %+v", defaultPodInfo, outPodInfo)
|
t.Errorf("Expected PodInfoOnMount to be defaulted to: %+v, got: %+v", defaultPodInfo, outPodInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSetDefaultVolumeLifecycleModesEnabled(t *testing.T) {
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
|
||||||
|
driver := &storagev1beta1.CSIDriver{}
|
||||||
|
|
||||||
|
// field should be defaulted
|
||||||
|
defaultMode := storagev1beta1.VolumeLifecyclePersistent
|
||||||
|
output := roundTrip(t, runtime.Object(driver)).(*storagev1beta1.CSIDriver)
|
||||||
|
outModes := output.Spec.VolumeLifecycleModes
|
||||||
|
if len(outModes) != 1 {
|
||||||
|
t.Errorf("Expected VolumeLifecycleModes to be defaulted to: %+v, got: %+v", defaultMode, outModes)
|
||||||
|
} else if outModes[0] != defaultMode {
|
||||||
|
t.Errorf("Expected VolumeLifecycleModes to be defaulted to: %+v, got: %+v", defaultMode, outModes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetDefaultVolumeLifecycleModesDisabled(t *testing.T) {
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, false)()
|
||||||
|
driver := &storagev1beta1.CSIDriver{}
|
||||||
|
|
||||||
|
// field should not be defaulted
|
||||||
|
output := roundTrip(t, runtime.Object(driver)).(*storagev1beta1.CSIDriver)
|
||||||
|
outModes := output.Spec.VolumeLifecycleModes
|
||||||
|
if outModes != nil {
|
||||||
|
t.Errorf("Expected VolumeLifecycleModes to remain nil, got: %+v", outModes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -253,6 +253,7 @@ func Convert_storage_CSIDriverList_To_v1beta1_CSIDriverList(in *storage.CSIDrive
|
|||||||
func autoConvert_v1beta1_CSIDriverSpec_To_storage_CSIDriverSpec(in *v1beta1.CSIDriverSpec, out *storage.CSIDriverSpec, s conversion.Scope) error {
|
func autoConvert_v1beta1_CSIDriverSpec_To_storage_CSIDriverSpec(in *v1beta1.CSIDriverSpec, out *storage.CSIDriverSpec, s conversion.Scope) error {
|
||||||
out.AttachRequired = (*bool)(unsafe.Pointer(in.AttachRequired))
|
out.AttachRequired = (*bool)(unsafe.Pointer(in.AttachRequired))
|
||||||
out.PodInfoOnMount = (*bool)(unsafe.Pointer(in.PodInfoOnMount))
|
out.PodInfoOnMount = (*bool)(unsafe.Pointer(in.PodInfoOnMount))
|
||||||
|
out.VolumeLifecycleModes = *(*[]storage.VolumeLifecycleMode)(unsafe.Pointer(&in.VolumeLifecycleModes))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,6 +265,7 @@ func Convert_v1beta1_CSIDriverSpec_To_storage_CSIDriverSpec(in *v1beta1.CSIDrive
|
|||||||
func autoConvert_storage_CSIDriverSpec_To_v1beta1_CSIDriverSpec(in *storage.CSIDriverSpec, out *v1beta1.CSIDriverSpec, s conversion.Scope) error {
|
func autoConvert_storage_CSIDriverSpec_To_v1beta1_CSIDriverSpec(in *storage.CSIDriverSpec, out *v1beta1.CSIDriverSpec, s conversion.Scope) error {
|
||||||
out.AttachRequired = (*bool)(unsafe.Pointer(in.AttachRequired))
|
out.AttachRequired = (*bool)(unsafe.Pointer(in.AttachRequired))
|
||||||
out.PodInfoOnMount = (*bool)(unsafe.Pointer(in.PodInfoOnMount))
|
out.PodInfoOnMount = (*bool)(unsafe.Pointer(in.PodInfoOnMount))
|
||||||
|
out.VolumeLifecycleModes = *(*[]v1beta1.VolumeLifecycleMode)(unsafe.Pointer(&in.VolumeLifecycleModes))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,6 +419,7 @@ func validateCSIDriverSpec(
|
|||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
allErrs = append(allErrs, validateAttachRequired(spec.AttachRequired, fldPath.Child("attachedRequired"))...)
|
allErrs = append(allErrs, validateAttachRequired(spec.AttachRequired, fldPath.Child("attachedRequired"))...)
|
||||||
allErrs = append(allErrs, validatePodInfoOnMount(spec.PodInfoOnMount, fldPath.Child("podInfoOnMount"))...)
|
allErrs = append(allErrs, validatePodInfoOnMount(spec.PodInfoOnMount, fldPath.Child("podInfoOnMount"))...)
|
||||||
|
allErrs = append(allErrs, validateVolumeLifecycleModes(spec.VolumeLifecycleModes, fldPath.Child("volumeLifecycleModes"))...)
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,3 +442,21 @@ func validatePodInfoOnMount(podInfoOnMount *bool, fldPath *field.Path) field.Err
|
|||||||
|
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validateVolumeLifecycleModes tests if mode has one of the allowed values.
|
||||||
|
func validateVolumeLifecycleModes(modes []storage.VolumeLifecycleMode, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
for _, mode := range modes {
|
||||||
|
switch mode {
|
||||||
|
case storage.VolumeLifecyclePersistent, storage.VolumeLifecycleEphemeral:
|
||||||
|
default:
|
||||||
|
allErrs = append(allErrs, field.NotSupported(fldPath, mode,
|
||||||
|
[]string{
|
||||||
|
string(storage.VolumeLifecyclePersistent),
|
||||||
|
string(storage.VolumeLifecycleEphemeral),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
@ -1726,6 +1726,49 @@ func TestCSIDriverValidation(t *testing.T) {
|
|||||||
PodInfoOnMount: ¬PodInfoOnMount,
|
PodInfoOnMount: ¬PodInfoOnMount,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: driverName},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachNotRequired,
|
||||||
|
PodInfoOnMount: ¬PodInfoOnMount,
|
||||||
|
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecyclePersistent,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: driverName},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachNotRequired,
|
||||||
|
PodInfoOnMount: ¬PodInfoOnMount,
|
||||||
|
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecycleEphemeral,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: driverName},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachNotRequired,
|
||||||
|
PodInfoOnMount: ¬PodInfoOnMount,
|
||||||
|
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecycleEphemeral,
|
||||||
|
storage.VolumeLifecyclePersistent,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: driverName},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachNotRequired,
|
||||||
|
PodInfoOnMount: ¬PodInfoOnMount,
|
||||||
|
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecycleEphemeral,
|
||||||
|
storage.VolumeLifecyclePersistent,
|
||||||
|
storage.VolumeLifecycleEphemeral,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, csiDriver := range successCases {
|
for _, csiDriver := range successCases {
|
||||||
@ -1764,6 +1807,17 @@ func TestCSIDriverValidation(t *testing.T) {
|
|||||||
PodInfoOnMount: nil,
|
PodInfoOnMount: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// invalid mode
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: driverName},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachNotRequired,
|
||||||
|
PodInfoOnMount: ¬PodInfoOnMount,
|
||||||
|
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||||
|
"no-such-mode",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, csiDriver := range errorCases {
|
for _, csiDriver := range errorCases {
|
||||||
@ -1772,3 +1826,94 @@ func TestCSIDriverValidation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCSIDriverValidationUpdate(t *testing.T) {
|
||||||
|
driverName := "test-driver"
|
||||||
|
longName := "my-a-b-c-d-c-f-g-h-i-j-k-l-m-n-o-p-q-r-s-t-u-v-w-x-y-z-ABCDEFGHIJKLMNOPQRSTUVWXYZ-driver"
|
||||||
|
invalidName := "-invalid-@#$%^&*()-"
|
||||||
|
attachRequired := true
|
||||||
|
attachNotRequired := false
|
||||||
|
podInfoOnMount := true
|
||||||
|
notPodInfoOnMount := false
|
||||||
|
old := storage.CSIDriver{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: driverName},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachNotRequired,
|
||||||
|
PodInfoOnMount: ¬PodInfoOnMount,
|
||||||
|
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecycleEphemeral,
|
||||||
|
storage.VolumeLifecyclePersistent,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currently there is only one success case: exactly the same
|
||||||
|
// as the existing object.
|
||||||
|
successCases := []storage.CSIDriver{old}
|
||||||
|
for _, csiDriver := range successCases {
|
||||||
|
if errs := ValidateCSIDriverUpdate(&csiDriver, &old); len(errs) != 0 {
|
||||||
|
t.Errorf("expected success for %+v: %v", csiDriver, errs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errorCases := []storage.CSIDriver{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: invalidName},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachRequired,
|
||||||
|
PodInfoOnMount: &podInfoOnMount,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: longName},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachNotRequired,
|
||||||
|
PodInfoOnMount: ¬PodInfoOnMount,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// AttachRequired not set
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: driverName},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: nil,
|
||||||
|
PodInfoOnMount: &podInfoOnMount,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// AttachRequired not set
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: driverName},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachNotRequired,
|
||||||
|
PodInfoOnMount: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// invalid mode
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: driverName},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachNotRequired,
|
||||||
|
PodInfoOnMount: ¬PodInfoOnMount,
|
||||||
|
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||||
|
"no-such-mode",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// different modes
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: driverName},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachNotRequired,
|
||||||
|
PodInfoOnMount: ¬PodInfoOnMount,
|
||||||
|
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecycleEphemeral,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, csiDriver := range errorCases {
|
||||||
|
if errs := ValidateCSIDriverUpdate(&csiDriver, &old); len(errs) == 0 {
|
||||||
|
t.Errorf("Expected failure for test: %v", csiDriver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
5
pkg/apis/storage/zz_generated.deepcopy.go
generated
5
pkg/apis/storage/zz_generated.deepcopy.go
generated
@ -98,6 +98,11 @@ func (in *CSIDriverSpec) DeepCopyInto(out *CSIDriverSpec) {
|
|||||||
*out = new(bool)
|
*out = new(bool)
|
||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
|
if in.VolumeLifecycleModes != nil {
|
||||||
|
in, out := &in.VolumeLifecycleModes, &out.VolumeLifecycleModes
|
||||||
|
*out = make([]VolumeLifecycleMode, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,9 +12,11 @@ go_library(
|
|||||||
"//pkg/api/legacyscheme:go_default_library",
|
"//pkg/api/legacyscheme:go_default_library",
|
||||||
"//pkg/apis/storage:go_default_library",
|
"//pkg/apis/storage:go_default_library",
|
||||||
"//pkg/apis/storage/validation:go_default_library",
|
"//pkg/apis/storage/validation:go_default_library",
|
||||||
|
"//pkg/features:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -41,8 +43,12 @@ go_test(
|
|||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/apis/storage:go_default_library",
|
"//pkg/apis/storage:go_default_library",
|
||||||
|
"//pkg/features:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||||
|
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
|
||||||
|
"//vendor/github.com/stretchr/testify/require:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -22,9 +22,11 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
"k8s.io/apiserver/pkg/storage/names"
|
"k8s.io/apiserver/pkg/storage/names"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
"k8s.io/kubernetes/pkg/apis/storage"
|
"k8s.io/kubernetes/pkg/apis/storage"
|
||||||
"k8s.io/kubernetes/pkg/apis/storage/validation"
|
"k8s.io/kubernetes/pkg/apis/storage/validation"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
)
|
)
|
||||||
|
|
||||||
// csiDriverStrategy implements behavior for CSIDriver objects
|
// csiDriverStrategy implements behavior for CSIDriver objects
|
||||||
@ -41,8 +43,12 @@ func (csiDriverStrategy) NamespaceScoped() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetBeforeCreate clears the Status field which is not allowed to be set by end users on creation.
|
// PrepareForCreate clears the VolumeLifecycleModes field if the corresponding feature is disabled.
|
||||||
func (csiDriverStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
|
func (csiDriverStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
|
||||||
|
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
|
||||||
|
csiDriver := obj.(*storage.CSIDriver)
|
||||||
|
csiDriver.Spec.VolumeLifecycleModes = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (csiDriverStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
|
func (csiDriverStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
|
||||||
@ -62,8 +68,15 @@ func (csiDriverStrategy) AllowCreateOnUpdate() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrepareForUpdate sets the Status fields which is not allowed to be set by an end user updating a CSIDriver
|
// PrepareForUpdate clears the VolumeLifecycleModes field if the corresponding feature is disabled and
|
||||||
|
// existing object does not already have that field set. This allows the field to remain when
|
||||||
|
// downgrading to a version that has the feature disabled.
|
||||||
func (csiDriverStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
|
func (csiDriverStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
|
||||||
|
if old.(*storage.CSIDriver).Spec.VolumeLifecycleModes == nil &&
|
||||||
|
!utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
|
||||||
|
newCSIDriver := obj.(*storage.CSIDriver)
|
||||||
|
newCSIDriver.Spec.VolumeLifecycleModes = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (csiDriverStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
|
func (csiDriverStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
|
||||||
|
@ -19,10 +19,14 @@ package csidriver
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
"k8s.io/kubernetes/pkg/apis/storage"
|
"k8s.io/kubernetes/pkg/apis/storage"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getValidCSIDriver(name string) *storage.CSIDriver {
|
func getValidCSIDriver(name string) *storage.CSIDriver {
|
||||||
@ -74,6 +78,169 @@ func TestCSIDriverStrategy(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCSIDriverPrepareForCreate(t *testing.T) {
|
||||||
|
ctx := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{
|
||||||
|
APIGroup: "storage.k8s.io",
|
||||||
|
APIVersion: "v1beta1",
|
||||||
|
Resource: "csidrivers",
|
||||||
|
})
|
||||||
|
|
||||||
|
attachRequired := true
|
||||||
|
podInfoOnMount := true
|
||||||
|
csiDriver := &storage.CSIDriver{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachRequired,
|
||||||
|
PodInfoOnMount: &podInfoOnMount,
|
||||||
|
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecyclePersistent,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
withInline bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "inline enabled",
|
||||||
|
withInline: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "inline disabled",
|
||||||
|
withInline: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, test.withInline)()
|
||||||
|
|
||||||
|
Strategy.PrepareForCreate(ctx, csiDriver)
|
||||||
|
errs := Strategy.Validate(ctx, csiDriver)
|
||||||
|
if len(errs) != 0 {
|
||||||
|
t.Errorf("unexpected validating errors: %v", errs)
|
||||||
|
}
|
||||||
|
if test.withInline {
|
||||||
|
if len(csiDriver.Spec.VolumeLifecycleModes) != 1 {
|
||||||
|
t.Errorf("VolumeLifecycleModes modified: %v", csiDriver.Spec)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if len(csiDriver.Spec.VolumeLifecycleModes) != 0 {
|
||||||
|
t.Errorf("VolumeLifecycleModes not stripped: %v", csiDriver.Spec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCSIDriverPrepareForUpdate(t *testing.T) {
|
||||||
|
ctx := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{
|
||||||
|
APIGroup: "storage.k8s.io",
|
||||||
|
APIVersion: "v1beta1",
|
||||||
|
Resource: "csidrivers",
|
||||||
|
})
|
||||||
|
|
||||||
|
attachRequired := true
|
||||||
|
podInfoOnMount := true
|
||||||
|
driverWithoutModes := &storage.CSIDriver{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachRequired,
|
||||||
|
PodInfoOnMount: &podInfoOnMount,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
driverWithPersistent := &storage.CSIDriver{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachRequired,
|
||||||
|
PodInfoOnMount: &podInfoOnMount,
|
||||||
|
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecyclePersistent,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
driverWithEphemeral := &storage.CSIDriver{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachRequired,
|
||||||
|
PodInfoOnMount: &podInfoOnMount,
|
||||||
|
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecycleEphemeral,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
var resultEmpty []storage.VolumeLifecycleMode
|
||||||
|
resultPersistent := []storage.VolumeLifecycleMode{storage.VolumeLifecyclePersistent}
|
||||||
|
resultEphemeral := []storage.VolumeLifecycleMode{storage.VolumeLifecycleEphemeral}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
old, update *storage.CSIDriver
|
||||||
|
withInline, withoutInline []storage.VolumeLifecycleMode
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "before: no mode, update: no mode",
|
||||||
|
old: driverWithoutModes,
|
||||||
|
update: driverWithoutModes,
|
||||||
|
withInline: resultEmpty,
|
||||||
|
withoutInline: resultEmpty,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "before: no mode, update: persistent",
|
||||||
|
old: driverWithoutModes,
|
||||||
|
update: driverWithPersistent,
|
||||||
|
withInline: resultPersistent,
|
||||||
|
withoutInline: resultEmpty,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "before: persistent, update: ephemeral",
|
||||||
|
old: driverWithPersistent,
|
||||||
|
update: driverWithEphemeral,
|
||||||
|
withInline: resultEphemeral,
|
||||||
|
withoutInline: resultEphemeral,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "before: persistent, update: no mode",
|
||||||
|
old: driverWithPersistent,
|
||||||
|
update: driverWithoutModes,
|
||||||
|
withInline: resultEmpty,
|
||||||
|
withoutInline: resultEmpty,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
runAll := func(t *testing.T, withInline bool) {
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, withInline)()
|
||||||
|
|
||||||
|
csiDriver := test.update.DeepCopy()
|
||||||
|
Strategy.PrepareForUpdate(ctx, csiDriver, test.old)
|
||||||
|
if withInline {
|
||||||
|
require.Equal(t, csiDriver.Spec.VolumeLifecycleModes, test.withInline)
|
||||||
|
} else {
|
||||||
|
require.Equal(t, csiDriver.Spec.VolumeLifecycleModes, test.withoutInline)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("with inline volumes", func(t *testing.T) {
|
||||||
|
runAll(t, true)
|
||||||
|
})
|
||||||
|
t.Run("without inline volumes", func(t *testing.T) {
|
||||||
|
runAll(t, false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestCSIDriverValidation(t *testing.T) {
|
func TestCSIDriverValidation(t *testing.T) {
|
||||||
attachRequired := true
|
attachRequired := true
|
||||||
notAttachRequired := false
|
notAttachRequired := false
|
||||||
@ -129,6 +296,71 @@ func TestCSIDriverValidation(t *testing.T) {
|
|||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"invalid volume mode",
|
||||||
|
&storage.CSIDriver{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachRequired,
|
||||||
|
PodInfoOnMount: &podInfoOnMount,
|
||||||
|
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecycleMode("no-such-mode"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"persistent volume mode",
|
||||||
|
&storage.CSIDriver{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachRequired,
|
||||||
|
PodInfoOnMount: &podInfoOnMount,
|
||||||
|
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecyclePersistent,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ephemeral volume mode",
|
||||||
|
&storage.CSIDriver{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachRequired,
|
||||||
|
PodInfoOnMount: &podInfoOnMount,
|
||||||
|
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecycleEphemeral,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"both volume modes",
|
||||||
|
&storage.CSIDriver{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
},
|
||||||
|
Spec: storage.CSIDriverSpec{
|
||||||
|
AttachRequired: &attachRequired,
|
||||||
|
PodInfoOnMount: &podInfoOnMount,
|
||||||
|
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||||
|
storage.VolumeLifecyclePersistent,
|
||||||
|
storage.VolumeLifecycleEphemeral,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
@ -23,6 +23,7 @@ go_library(
|
|||||||
"//pkg/volume/util:go_default_library",
|
"//pkg/volume/util:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/api/storage/v1:go_default_library",
|
"//staging/src/k8s.io/api/storage/v1:go_default_library",
|
||||||
|
"//staging/src/k8s.io/api/storage/v1beta1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
|
@ -342,9 +342,9 @@ func TestAttacherWithCSIDriver(t *testing.T) {
|
|||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
fakeClient := fakeclient.NewSimpleClientset(
|
fakeClient := fakeclient.NewSimpleClientset(
|
||||||
getTestCSIDriver("not-attachable", nil, &bFalse),
|
getTestCSIDriver("not-attachable", nil, &bFalse, nil),
|
||||||
getTestCSIDriver("attachable", nil, &bTrue),
|
getTestCSIDriver("attachable", nil, &bTrue, nil),
|
||||||
getTestCSIDriver("nil", nil, nil),
|
getTestCSIDriver("nil", nil, nil, nil),
|
||||||
)
|
)
|
||||||
plug, fakeWatcher, tmpDir, _ := newTestWatchPlugin(t, fakeClient)
|
plug, fakeWatcher, tmpDir, _ := newTestWatchPlugin(t, fakeClient)
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
@ -430,9 +430,9 @@ func TestAttacherWaitForVolumeAttachmentWithCSIDriver(t *testing.T) {
|
|||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
fakeClient := fakeclient.NewSimpleClientset(
|
fakeClient := fakeclient.NewSimpleClientset(
|
||||||
getTestCSIDriver("not-attachable", nil, &bFalse),
|
getTestCSIDriver("not-attachable", nil, &bFalse, nil),
|
||||||
getTestCSIDriver("attachable", nil, &bTrue),
|
getTestCSIDriver("attachable", nil, &bTrue, nil),
|
||||||
getTestCSIDriver("nil", nil, nil),
|
getTestCSIDriver("nil", nil, nil, nil),
|
||||||
)
|
)
|
||||||
plug, tmpDir := newTestPlugin(t, fakeClient)
|
plug, tmpDir := newTestPlugin(t, fakeClient)
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
|
||||||
api "k8s.io/api/core/v1"
|
api "k8s.io/api/core/v1"
|
||||||
|
storage "k8s.io/api/storage/v1beta1"
|
||||||
apierrs "k8s.io/apimachinery/pkg/api/errors"
|
apierrs "k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
@ -46,14 +47,14 @@ var (
|
|||||||
driverName,
|
driverName,
|
||||||
nodeName,
|
nodeName,
|
||||||
attachmentID,
|
attachmentID,
|
||||||
csiVolumeMode string
|
volumeLifecycleMode string
|
||||||
}{
|
}{
|
||||||
"specVolID",
|
"specVolID",
|
||||||
"volumeHandle",
|
"volumeHandle",
|
||||||
"driverName",
|
"driverName",
|
||||||
"nodeName",
|
"nodeName",
|
||||||
"attachmentID",
|
"attachmentID",
|
||||||
"csiVolumeMode",
|
"volumeLifecycleMode",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -62,7 +63,7 @@ type csiMountMgr struct {
|
|||||||
k8s kubernetes.Interface
|
k8s kubernetes.Interface
|
||||||
plugin *csiPlugin
|
plugin *csiPlugin
|
||||||
driverName csiDriverName
|
driverName csiDriverName
|
||||||
csiVolumeMode csiVolumeMode
|
volumeLifecycleMode storage.VolumeLifecycleMode
|
||||||
volumeID string
|
volumeID string
|
||||||
specVolumeID string
|
specVolumeID string
|
||||||
readOnly bool
|
readOnly bool
|
||||||
@ -145,8 +146,8 @@ func (c *csiMountMgr) SetUpAt(dir string, mounterArgs volume.MounterArgs) error
|
|||||||
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
|
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
|
||||||
return fmt.Errorf("CSIInlineVolume feature required")
|
return fmt.Errorf("CSIInlineVolume feature required")
|
||||||
}
|
}
|
||||||
if c.csiVolumeMode != ephemeralVolumeMode {
|
if c.volumeLifecycleMode != storage.VolumeLifecycleEphemeral {
|
||||||
return fmt.Errorf("unexpected volume mode: %s", c.csiVolumeMode)
|
return fmt.Errorf("unexpected volume mode: %s", c.volumeLifecycleMode)
|
||||||
}
|
}
|
||||||
if volSrc.FSType != nil {
|
if volSrc.FSType != nil {
|
||||||
fsType = *volSrc.FSType
|
fsType = *volSrc.FSType
|
||||||
@ -160,8 +161,8 @@ func (c *csiMountMgr) SetUpAt(dir string, mounterArgs volume.MounterArgs) error
|
|||||||
secretRef = &api.SecretReference{Name: secretName, Namespace: ns}
|
secretRef = &api.SecretReference{Name: secretName, Namespace: ns}
|
||||||
}
|
}
|
||||||
case pvSrc != nil:
|
case pvSrc != nil:
|
||||||
if c.csiVolumeMode != persistentVolumeMode {
|
if c.volumeLifecycleMode != storage.VolumeLifecyclePersistent {
|
||||||
return fmt.Errorf("unexpected driver mode: %s", c.csiVolumeMode)
|
return fmt.Errorf("unexpected driver mode: %s", c.volumeLifecycleMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
fsType = pvSrc.FSType
|
fsType = pvSrc.FSType
|
||||||
@ -319,7 +320,7 @@ func (c *csiMountMgr) podAttributes() (map[string]string, error) {
|
|||||||
"csi.storage.k8s.io/serviceAccount.name": c.pod.Spec.ServiceAccountName,
|
"csi.storage.k8s.io/serviceAccount.name": c.pod.Spec.ServiceAccountName,
|
||||||
}
|
}
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
|
if utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
|
||||||
attrs["csi.storage.k8s.io/ephemeral"] = strconv.FormatBool(c.csiVolumeMode == ephemeralVolumeMode)
|
attrs["csi.storage.k8s.io/ephemeral"] = strconv.FormatBool(c.volumeLifecycleMode == storage.VolumeLifecycleEphemeral)
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.V(4).Infof(log("CSIDriver %q requires pod information", c.driverName))
|
klog.V(4).Infof(log("CSIDriver %q requires pod information", c.driverName))
|
||||||
|
@ -28,6 +28,7 @@ import (
|
|||||||
|
|
||||||
api "k8s.io/api/core/v1"
|
api "k8s.io/api/core/v1"
|
||||||
storage "k8s.io/api/storage/v1"
|
storage "k8s.io/api/storage/v1"
|
||||||
|
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
||||||
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
@ -151,13 +152,16 @@ func MounterSetUpTests(t *testing.T, podInfoEnabled bool) {
|
|||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
klog.Infof("Starting test %s", test.name)
|
klog.Infof("Starting test %s", test.name)
|
||||||
|
// Modes must be set if (and only if) CSIInlineVolume is enabled.
|
||||||
|
var modes []storagev1beta1.VolumeLifecycleMode
|
||||||
if test.csiInlineVolume {
|
if test.csiInlineVolume {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
|
||||||
|
modes = append(modes, storagev1beta1.VolumeLifecyclePersistent)
|
||||||
}
|
}
|
||||||
fakeClient := fakeclient.NewSimpleClientset(
|
fakeClient := fakeclient.NewSimpleClientset(
|
||||||
getTestCSIDriver("no-info", &noPodMountInfo, nil),
|
getTestCSIDriver("no-info", &noPodMountInfo, nil, modes),
|
||||||
getTestCSIDriver("info", ¤tPodInfoMount, nil),
|
getTestCSIDriver("info", ¤tPodInfoMount, nil, modes),
|
||||||
getTestCSIDriver("nil", nil, nil),
|
getTestCSIDriver("nil", nil, nil, modes),
|
||||||
)
|
)
|
||||||
plug, tmpDir := newTestPlugin(t, fakeClient)
|
plug, tmpDir := newTestPlugin(t, fakeClient)
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
@ -278,16 +282,16 @@ func TestMounterSetUpSimple(t *testing.T) {
|
|||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
podUID types.UID
|
podUID types.UID
|
||||||
mode csiVolumeMode
|
mode storagev1beta1.VolumeLifecycleMode
|
||||||
fsType string
|
fsType string
|
||||||
options []string
|
options []string
|
||||||
spec func(string, []string) *volume.Spec
|
spec func(string, []string) *volume.Spec
|
||||||
shouldFail bool
|
shouldFail bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "setup with vol source",
|
name: "setup with ephemeral source",
|
||||||
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
||||||
mode: ephemeralVolumeMode,
|
mode: storagev1beta1.VolumeLifecycleEphemeral,
|
||||||
fsType: "ext4",
|
fsType: "ext4",
|
||||||
shouldFail: true,
|
shouldFail: true,
|
||||||
spec: func(fsType string, options []string) *volume.Spec {
|
spec: func(fsType string, options []string) *volume.Spec {
|
||||||
@ -299,7 +303,7 @@ func TestMounterSetUpSimple(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "setup with persistent source",
|
name: "setup with persistent source",
|
||||||
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
||||||
mode: persistentVolumeMode,
|
mode: storagev1beta1.VolumeLifecyclePersistent,
|
||||||
fsType: "zfs",
|
fsType: "zfs",
|
||||||
spec: func(fsType string, options []string) *volume.Spec {
|
spec: func(fsType string, options []string) *volume.Spec {
|
||||||
pvSrc := makeTestPV("pv1", 20, testDriver, "vol1")
|
pvSrc := makeTestPV("pv1", 20, testDriver, "vol1")
|
||||||
@ -311,7 +315,7 @@ func TestMounterSetUpSimple(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "setup with persistent source without unspecified fstype and options",
|
name: "setup with persistent source without unspecified fstype and options",
|
||||||
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
||||||
mode: persistentVolumeMode,
|
mode: storagev1beta1.VolumeLifecyclePersistent,
|
||||||
spec: func(fsType string, options []string) *volume.Spec {
|
spec: func(fsType string, options []string) *volume.Spec {
|
||||||
return volume.NewSpecFromPersistentVolume(makeTestPV("pv1", 20, testDriver, "vol2"), false)
|
return volume.NewSpecFromPersistentVolume(makeTestPV("pv1", 20, testDriver, "vol2"), false)
|
||||||
},
|
},
|
||||||
@ -345,8 +349,8 @@ func TestMounterSetUpSimple(t *testing.T) {
|
|||||||
csiMounter := mounter.(*csiMountMgr)
|
csiMounter := mounter.(*csiMountMgr)
|
||||||
csiMounter.csiClient = setupClient(t, true)
|
csiMounter.csiClient = setupClient(t, true)
|
||||||
|
|
||||||
if csiMounter.csiVolumeMode != persistentVolumeMode {
|
if csiMounter.volumeLifecycleMode != storagev1beta1.VolumeLifecyclePersistent {
|
||||||
t.Fatal("unexpected volume mode: ", csiMounter.csiVolumeMode)
|
t.Fatal("unexpected volume mode: ", csiMounter.volumeLifecycleMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
attachID := getAttachmentName(csiMounter.volumeID, string(csiMounter.driverName), string(plug.host.GetNodeName()))
|
attachID := getAttachmentName(csiMounter.volumeID, string(csiMounter.driverName), string(plug.host.GetNodeName()))
|
||||||
@ -397,14 +401,10 @@ func TestMounterSetUpSimple(t *testing.T) {
|
|||||||
func TestMounterSetUpWithInline(t *testing.T) {
|
func TestMounterSetUpWithInline(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
|
||||||
|
|
||||||
fakeClient := fakeclient.NewSimpleClientset()
|
|
||||||
plug, tmpDir := newTestPlugin(t, fakeClient)
|
|
||||||
defer os.RemoveAll(tmpDir)
|
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
podUID types.UID
|
podUID types.UID
|
||||||
mode csiVolumeMode
|
mode storagev1beta1.VolumeLifecycleMode
|
||||||
fsType string
|
fsType string
|
||||||
options []string
|
options []string
|
||||||
spec func(string, []string) *volume.Spec
|
spec func(string, []string) *volume.Spec
|
||||||
@ -413,7 +413,7 @@ func TestMounterSetUpWithInline(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "setup with vol source",
|
name: "setup with vol source",
|
||||||
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
||||||
mode: ephemeralVolumeMode,
|
mode: storagev1beta1.VolumeLifecycleEphemeral,
|
||||||
fsType: "ext4",
|
fsType: "ext4",
|
||||||
spec: func(fsType string, options []string) *volume.Spec {
|
spec: func(fsType string, options []string) *volume.Spec {
|
||||||
volSrc := makeTestVol("pv1", testDriver)
|
volSrc := makeTestVol("pv1", testDriver)
|
||||||
@ -424,7 +424,7 @@ func TestMounterSetUpWithInline(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "setup with persistent source",
|
name: "setup with persistent source",
|
||||||
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
||||||
mode: persistentVolumeMode,
|
mode: storagev1beta1.VolumeLifecyclePersistent,
|
||||||
fsType: "zfs",
|
fsType: "zfs",
|
||||||
spec: func(fsType string, options []string) *volume.Spec {
|
spec: func(fsType string, options []string) *volume.Spec {
|
||||||
pvSrc := makeTestPV("pv1", 20, testDriver, "vol1")
|
pvSrc := makeTestPV("pv1", 20, testDriver, "vol1")
|
||||||
@ -436,7 +436,7 @@ func TestMounterSetUpWithInline(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "setup with persistent source without unspecified fstype and options",
|
name: "setup with persistent source without unspecified fstype and options",
|
||||||
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
||||||
mode: persistentVolumeMode,
|
mode: storagev1beta1.VolumeLifecyclePersistent,
|
||||||
spec: func(fsType string, options []string) *volume.Spec {
|
spec: func(fsType string, options []string) *volume.Spec {
|
||||||
return volume.NewSpecFromPersistentVolume(makeTestPV("pv1", 20, testDriver, "vol2"), false)
|
return volume.NewSpecFromPersistentVolume(makeTestPV("pv1", 20, testDriver, "vol2"), false)
|
||||||
},
|
},
|
||||||
@ -449,6 +449,15 @@ func TestMounterSetUpWithInline(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
// The fake driver currently supports all modes.
|
||||||
|
volumeLifecycleModes := []storagev1beta1.VolumeLifecycleMode{
|
||||||
|
storagev1beta1.VolumeLifecycleEphemeral,
|
||||||
|
storagev1beta1.VolumeLifecyclePersistent,
|
||||||
|
}
|
||||||
|
driver := getTestCSIDriver(testDriver, nil, nil, volumeLifecycleModes)
|
||||||
|
fakeClient := fakeclient.NewSimpleClientset(driver)
|
||||||
|
plug, tmpDir := newTestPlugin(t, fakeClient)
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
registerFakePlugin(testDriver, "endpoint", []string{"1.0.0"}, t)
|
registerFakePlugin(testDriver, "endpoint", []string{"1.0.0"}, t)
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
mounter, err := plug.NewMounter(
|
mounter, err := plug.NewMounter(
|
||||||
@ -470,15 +479,15 @@ func TestMounterSetUpWithInline(t *testing.T) {
|
|||||||
csiMounter := mounter.(*csiMountMgr)
|
csiMounter := mounter.(*csiMountMgr)
|
||||||
csiMounter.csiClient = setupClient(t, true)
|
csiMounter.csiClient = setupClient(t, true)
|
||||||
|
|
||||||
if csiMounter.csiVolumeMode != tc.mode {
|
if csiMounter.volumeLifecycleMode != tc.mode {
|
||||||
t.Fatal("unexpected volume mode: ", csiMounter.csiVolumeMode)
|
t.Fatal("unexpected volume mode: ", csiMounter.volumeLifecycleMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
if csiMounter.csiVolumeMode == ephemeralVolumeMode && csiMounter.volumeID != makeVolumeHandle(string(tc.podUID), csiMounter.specVolumeID) {
|
if csiMounter.volumeLifecycleMode == storagev1beta1.VolumeLifecycleEphemeral && csiMounter.volumeID != makeVolumeHandle(string(tc.podUID), csiMounter.specVolumeID) {
|
||||||
t.Fatal("unexpected generated volumeHandle:", csiMounter.volumeID)
|
t.Fatal("unexpected generated volumeHandle:", csiMounter.volumeID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if csiMounter.csiVolumeMode == persistentVolumeMode {
|
if csiMounter.volumeLifecycleMode == storagev1beta1.VolumeLifecyclePersistent {
|
||||||
attachID := getAttachmentName(csiMounter.volumeID, string(csiMounter.driverName), string(plug.host.GetNodeName()))
|
attachID := getAttachmentName(csiMounter.volumeID, string(csiMounter.driverName), string(plug.host.GetNodeName()))
|
||||||
attachment := makeTestAttachment(attachID, "test-node", csiMounter.spec.Name())
|
attachment := makeTestAttachment(attachID, "test-node", csiMounter.spec.Name())
|
||||||
_, err = csiMounter.k8s.StorageV1().VolumeAttachments().Create(attachment)
|
_, err = csiMounter.k8s.StorageV1().VolumeAttachments().Create(attachment)
|
||||||
@ -503,10 +512,10 @@ func TestMounterSetUpWithInline(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validate stagingTargetPath
|
// validate stagingTargetPath
|
||||||
if tc.mode == ephemeralVolumeMode && vol.DeviceMountPath != "" {
|
if tc.mode == storagev1beta1.VolumeLifecycleEphemeral && vol.DeviceMountPath != "" {
|
||||||
t.Errorf("unexpected devicePathTarget sent to driver: %s", vol.DeviceMountPath)
|
t.Errorf("unexpected devicePathTarget sent to driver: %s", vol.DeviceMountPath)
|
||||||
}
|
}
|
||||||
if tc.mode == persistentVolumeMode {
|
if tc.mode == storagev1beta1.VolumeLifecyclePersistent {
|
||||||
devicePath, err := makeDeviceMountPath(plug, csiMounter.spec)
|
devicePath, err := makeDeviceMountPath(plug, csiMounter.spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -30,6 +30,7 @@ import (
|
|||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
|
||||||
api "k8s.io/api/core/v1"
|
api "k8s.io/api/core/v1"
|
||||||
|
storage "k8s.io/api/storage/v1beta1"
|
||||||
apierrs "k8s.io/apimachinery/pkg/api/errors"
|
apierrs "k8s.io/apimachinery/pkg/api/errors"
|
||||||
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
@ -67,18 +68,6 @@ type csiPlugin struct {
|
|||||||
csiDriverLister storagelisters.CSIDriverLister
|
csiDriverLister storagelisters.CSIDriverLister
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO (vladimirvivien) add this type to storage api
|
|
||||||
type driverMode string
|
|
||||||
|
|
||||||
const persistentDriverMode driverMode = "persistent"
|
|
||||||
const ephemeralDriverMode driverMode = "ephemeral"
|
|
||||||
const combinedDriverMode driverMode = "persistent+ephemeral"
|
|
||||||
|
|
||||||
type csiVolumeMode string
|
|
||||||
|
|
||||||
const persistentVolumeMode csiVolumeMode = "persistent"
|
|
||||||
const ephemeralVolumeMode csiVolumeMode = "ephemeral"
|
|
||||||
|
|
||||||
// ProbeVolumePlugins returns implemented plugins
|
// ProbeVolumePlugins returns implemented plugins
|
||||||
func ProbeVolumePlugins() []volume.VolumePlugin {
|
func ProbeVolumePlugins() []volume.VolumePlugin {
|
||||||
p := &csiPlugin{
|
p := &csiPlugin{
|
||||||
@ -373,15 +362,16 @@ func (p *csiPlugin) NewMounter(
|
|||||||
return nil, errors.New(log("volume source not found in volume.Spec"))
|
return nil, errors.New(log("volume source not found in volume.Spec"))
|
||||||
}
|
}
|
||||||
|
|
||||||
csiVolumeMode, err := p.getCSIVolumeMode(spec)
|
volumeLifecycleMode, err := p.getVolumeLifecycleMode(spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(pohly): check CSIDriver.Spec.Mode to ensure that the CSI driver
|
// Check CSIDriver.Spec.Mode to ensure that the CSI driver
|
||||||
// supports the current csiVolumeMode.
|
// supports the current volumeLifecycleMode.
|
||||||
// In alpha it is assumed that drivers are used correctly without
|
if err := p.supportsVolumeLifecycleMode(driverName, volumeLifecycleMode); err != nil {
|
||||||
// the additional sanity check.
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
k8s := p.host.GetKubeClient()
|
k8s := p.host.GetKubeClient()
|
||||||
if k8s == nil {
|
if k8s == nil {
|
||||||
@ -400,7 +390,7 @@ func (p *csiPlugin) NewMounter(
|
|||||||
pod: pod,
|
pod: pod,
|
||||||
podUID: pod.UID,
|
podUID: pod.UID,
|
||||||
driverName: csiDriverName(driverName),
|
driverName: csiDriverName(driverName),
|
||||||
csiVolumeMode: csiVolumeMode,
|
volumeLifecycleMode: volumeLifecycleMode,
|
||||||
volumeID: volumeHandle,
|
volumeID: volumeHandle,
|
||||||
specVolumeID: spec.Name(),
|
specVolumeID: spec.Name(),
|
||||||
readOnly: readOnly,
|
readOnly: readOnly,
|
||||||
@ -426,7 +416,7 @@ func (p *csiPlugin) NewMounter(
|
|||||||
volDataKey.volHandle: volumeHandle,
|
volDataKey.volHandle: volumeHandle,
|
||||||
volDataKey.driverName: driverName,
|
volDataKey.driverName: driverName,
|
||||||
volDataKey.nodeName: node,
|
volDataKey.nodeName: node,
|
||||||
volDataKey.csiVolumeMode: string(csiVolumeMode),
|
volDataKey.volumeLifecycleMode: string(volumeLifecycleMode),
|
||||||
}
|
}
|
||||||
|
|
||||||
attachID := getAttachmentName(volumeHandle, driverName, node)
|
attachID := getAttachmentName(volumeHandle, driverName, node)
|
||||||
@ -486,11 +476,11 @@ func (p *csiPlugin) ConstructVolumeSpec(volumeName, mountPath string) (*volume.S
|
|||||||
var spec *volume.Spec
|
var spec *volume.Spec
|
||||||
inlineEnabled := utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume)
|
inlineEnabled := utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume)
|
||||||
|
|
||||||
// If inlineEnabled is true and mode is ephemeralVolumeMode,
|
// If inlineEnabled is true and mode is VolumeLifecycleEphemeral,
|
||||||
// use constructVolSourceSpec to construct volume source spec.
|
// use constructVolSourceSpec to construct volume source spec.
|
||||||
// If inlineEnabled is false or mode is persistentVolumeMode,
|
// If inlineEnabled is false or mode is VolumeLifecyclePersistent,
|
||||||
// use constructPVSourceSpec to construct volume construct pv source spec.
|
// use constructPVSourceSpec to construct volume construct pv source spec.
|
||||||
if inlineEnabled && csiVolumeMode(volData[volDataKey.csiVolumeMode]) == ephemeralVolumeMode {
|
if inlineEnabled && storage.VolumeLifecycleMode(volData[volDataKey.volumeLifecycleMode]) == storage.VolumeLifecycleEphemeral {
|
||||||
spec = p.constructVolSourceSpec(volData[volDataKey.specVolID], volData[volDataKey.driverName])
|
spec = p.constructVolSourceSpec(volData[volDataKey.specVolID], volData[volDataKey.driverName])
|
||||||
return spec, nil
|
return spec, nil
|
||||||
}
|
}
|
||||||
@ -565,12 +555,12 @@ func (p *csiPlugin) NewDetacher() (volume.Detacher, error) {
|
|||||||
func (p *csiPlugin) CanAttach(spec *volume.Spec) (bool, error) {
|
func (p *csiPlugin) CanAttach(spec *volume.Spec) (bool, error) {
|
||||||
inlineEnabled := utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume)
|
inlineEnabled := utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume)
|
||||||
if inlineEnabled {
|
if inlineEnabled {
|
||||||
csiVolumeMode, err := p.getCSIVolumeMode(spec)
|
volumeLifecycleMode, err := p.getVolumeLifecycleMode(spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if csiVolumeMode == ephemeralVolumeMode {
|
if volumeLifecycleMode == storage.VolumeLifecycleEphemeral {
|
||||||
klog.V(5).Info(log("plugin.CanAttach = false, ephemeral mode detected for spec %v", spec.Name()))
|
klog.V(5).Info(log("plugin.CanAttach = false, ephemeral mode detected for spec %v", spec.Name()))
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
@ -599,12 +589,12 @@ func (p *csiPlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
csiVolumeMode, err := p.getCSIVolumeMode(spec)
|
volumeLifecycleMode, err := p.getVolumeLifecycleMode(spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if csiVolumeMode == ephemeralVolumeMode {
|
if volumeLifecycleMode == storage.VolumeLifecycleEphemeral {
|
||||||
klog.V(5).Info(log("plugin.CanDeviceMount skipped ephemeral mode detected for spec %v", spec.Name()))
|
klog.V(5).Info(log("plugin.CanDeviceMount skipped ephemeral mode detected for spec %v", spec.Name()))
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
@ -775,11 +765,67 @@ func (p *csiPlugin) skipAttach(driver string) (bool, error) {
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getCSIVolumeMode returns the mode for the specified spec: {persistent|ephemeral}.
|
// supportsVolumeMode checks whether the CSI driver supports a volume in the given mode.
|
||||||
|
// An error indicates that it isn't supported and explains why.
|
||||||
|
func (p *csiPlugin) supportsVolumeLifecycleMode(driver string, volumeMode storage.VolumeLifecycleMode) error {
|
||||||
|
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
|
||||||
|
// Feature disabled, therefore only "persistent" volumes are supported.
|
||||||
|
if volumeMode != storage.VolumeLifecyclePersistent {
|
||||||
|
return fmt.Errorf("CSIInlineVolume feature not enabled, %q volumes not supported", volumeMode)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve CSIDriver. It's not an error if that isn't
|
||||||
|
// possible (we don't have the lister if CSIDriverRegistry is
|
||||||
|
// disabled) or the driver isn't found (CSIDriver is
|
||||||
|
// optional), but then only persistent volumes are supported.
|
||||||
|
var csiDriver *storage.CSIDriver
|
||||||
|
if p.csiDriverLister != nil {
|
||||||
|
kletHost, ok := p.host.(volume.KubeletVolumeHost)
|
||||||
|
if ok {
|
||||||
|
kletHost.WaitForCacheSync()
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := p.csiDriverLister.Get(driver)
|
||||||
|
if err != nil && !apierrs.IsNotFound(err) {
|
||||||
|
// Some internal error.
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
csiDriver = c
|
||||||
|
}
|
||||||
|
|
||||||
|
// The right response depends on whether we have information
|
||||||
|
// about the driver and the volume mode.
|
||||||
|
switch {
|
||||||
|
case csiDriver == nil && volumeMode == storage.VolumeLifecyclePersistent:
|
||||||
|
// No information, but that's okay for persistent volumes (and only those).
|
||||||
|
return nil
|
||||||
|
case csiDriver == nil:
|
||||||
|
return fmt.Errorf("volume mode %q not supported by driver %s (no CSIDriver object)", volumeMode, driver)
|
||||||
|
case containsVolumeMode(csiDriver.Spec.VolumeLifecycleModes, volumeMode):
|
||||||
|
// Explicitly listed.
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("volume mode %q not supported by driver %s (only supports %q)", volumeMode, driver, csiDriver.Spec.VolumeLifecycleModes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// containsVolumeMode checks whether the given volume mode is listed.
|
||||||
|
func containsVolumeMode(modes []storage.VolumeLifecycleMode, mode storage.VolumeLifecycleMode) bool {
|
||||||
|
for _, m := range modes {
|
||||||
|
if m == mode {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// getVolumeLifecycleMode returns the mode for the specified spec: {persistent|ephemeral}.
|
||||||
// 1) If mode cannot be determined, it will default to "persistent".
|
// 1) If mode cannot be determined, it will default to "persistent".
|
||||||
// 2) If Mode cannot be resolved to either {persistent | ephemeral}, an error is returned
|
// 2) If Mode cannot be resolved to either {persistent | ephemeral}, an error is returned
|
||||||
// See https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/20190122-csi-inline-volumes.md
|
// See https://github.com/kubernetes/enhancements/blob/master/keps/sig-storage/20190122-csi-inline-volumes.md
|
||||||
func (p *csiPlugin) getCSIVolumeMode(spec *volume.Spec) (csiVolumeMode, error) {
|
func (p *csiPlugin) getVolumeLifecycleMode(spec *volume.Spec) (storage.VolumeLifecycleMode, error) {
|
||||||
// 1) if volume.Spec.Volume.CSI != nil -> mode is ephemeral
|
// 1) if volume.Spec.Volume.CSI != nil -> mode is ephemeral
|
||||||
// 2) if volume.Spec.PersistentVolume.Spec.CSI != nil -> persistent
|
// 2) if volume.Spec.PersistentVolume.Spec.CSI != nil -> persistent
|
||||||
volSrc, _, err := getSourceFromSpec(spec)
|
volSrc, _, err := getSourceFromSpec(spec)
|
||||||
@ -788,9 +834,9 @@ func (p *csiPlugin) getCSIVolumeMode(spec *volume.Spec) (csiVolumeMode, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if volSrc != nil && utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
|
if volSrc != nil && utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
|
||||||
return ephemeralVolumeMode, nil
|
return storage.VolumeLifecycleEphemeral, nil
|
||||||
}
|
}
|
||||||
return persistentVolumeMode, nil
|
return storage.VolumeLifecyclePersistent, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *csiPlugin) getPublishContext(client clientset.Interface, handle, driver, nodeName string) (map[string]string, error) {
|
func (p *csiPlugin) getPublishContext(client clientset.Interface, handle, driver, nodeName string) (map[string]string, error) {
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
api "k8s.io/api/core/v1"
|
api "k8s.io/api/core/v1"
|
||||||
|
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
||||||
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
@ -178,7 +179,12 @@ func TestPluginGetVolumeNameWithInline(t *testing.T) {
|
|||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
|
||||||
|
|
||||||
plug, tmpDir := newTestPlugin(t, nil)
|
modes := []storagev1beta1.VolumeLifecycleMode{
|
||||||
|
storagev1beta1.VolumeLifecyclePersistent,
|
||||||
|
}
|
||||||
|
driver := getTestCSIDriver(testDriver, nil, nil, modes)
|
||||||
|
client := fakeclient.NewSimpleClientset(driver)
|
||||||
|
plug, tmpDir := newTestPlugin(t, client)
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
@ -403,9 +409,6 @@ func TestPluginConstructVolumeSpecWithInline(t *testing.T) {
|
|||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
|
||||||
|
|
||||||
plug, tmpDir := newTestPlugin(t, nil)
|
|
||||||
defer os.RemoveAll(tmpDir)
|
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
originSpec *volume.Spec
|
originSpec *volume.Spec
|
||||||
@ -413,6 +416,7 @@ func TestPluginConstructVolumeSpecWithInline(t *testing.T) {
|
|||||||
volHandle string
|
volHandle string
|
||||||
podUID types.UID
|
podUID types.UID
|
||||||
shouldFail bool
|
shouldFail bool
|
||||||
|
modes []storagev1beta1.VolumeLifecycleMode
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "construct spec1 from persistent spec",
|
name: "construct spec1 from persistent spec",
|
||||||
@ -420,6 +424,7 @@ func TestPluginConstructVolumeSpecWithInline(t *testing.T) {
|
|||||||
volHandle: "testvol-handle1",
|
volHandle: "testvol-handle1",
|
||||||
originSpec: volume.NewSpecFromPersistentVolume(makeTestPV("test.vol.id", 20, testDriver, "testvol-handle1"), true),
|
originSpec: volume.NewSpecFromPersistentVolume(makeTestPV("test.vol.id", 20, testDriver, "testvol-handle1"), true),
|
||||||
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
||||||
|
modes: []storagev1beta1.VolumeLifecycleMode{storagev1beta1.VolumeLifecyclePersistent},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "construct spec2 from persistent spec",
|
name: "construct spec2 from persistent spec",
|
||||||
@ -427,18 +432,38 @@ func TestPluginConstructVolumeSpecWithInline(t *testing.T) {
|
|||||||
volHandle: "handle2",
|
volHandle: "handle2",
|
||||||
originSpec: volume.NewSpecFromPersistentVolume(makeTestPV("spec2", 20, testDriver, "handle2"), true),
|
originSpec: volume.NewSpecFromPersistentVolume(makeTestPV("spec2", 20, testDriver, "handle2"), true),
|
||||||
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
||||||
|
modes: []storagev1beta1.VolumeLifecycleMode{storagev1beta1.VolumeLifecyclePersistent},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "construct spec2 from persistent spec, missing mode",
|
||||||
|
specVolID: "spec2",
|
||||||
|
volHandle: "handle2",
|
||||||
|
originSpec: volume.NewSpecFromPersistentVolume(makeTestPV("spec2", 20, testDriver, "handle2"), true),
|
||||||
|
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
||||||
|
modes: []storagev1beta1.VolumeLifecycleMode{},
|
||||||
|
shouldFail: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "construct spec from volume spec",
|
name: "construct spec from volume spec",
|
||||||
specVolID: "volspec",
|
specVolID: "volspec",
|
||||||
originSpec: volume.NewSpecFromVolume(makeTestVol("volspec", testDriver)),
|
originSpec: volume.NewSpecFromVolume(makeTestVol("volspec", testDriver)),
|
||||||
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
||||||
|
modes: []storagev1beta1.VolumeLifecycleMode{storagev1beta1.VolumeLifecycleEphemeral},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "construct spec from volume spec2",
|
name: "construct spec from volume spec2",
|
||||||
specVolID: "volspec2",
|
specVolID: "volspec2",
|
||||||
originSpec: volume.NewSpecFromVolume(makeTestVol("volspec2", testDriver)),
|
originSpec: volume.NewSpecFromVolume(makeTestVol("volspec2", testDriver)),
|
||||||
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
||||||
|
modes: []storagev1beta1.VolumeLifecycleMode{storagev1beta1.VolumeLifecycleEphemeral},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "construct spec from volume spec2, missing mode",
|
||||||
|
specVolID: "volspec2",
|
||||||
|
originSpec: volume.NewSpecFromVolume(makeTestVol("volspec2", testDriver)),
|
||||||
|
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
||||||
|
modes: []storagev1beta1.VolumeLifecycleMode{},
|
||||||
|
shouldFail: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "missing spec",
|
name: "missing spec",
|
||||||
@ -451,6 +476,11 @@ func TestPluginConstructVolumeSpecWithInline(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
driver := getTestCSIDriver(testDriver, nil, nil, tc.modes)
|
||||||
|
client := fakeclient.NewSimpleClientset(driver)
|
||||||
|
plug, tmpDir := newTestPlugin(t, client)
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
mounter, err := plug.NewMounter(
|
mounter, err := plug.NewMounter(
|
||||||
tc.originSpec,
|
tc.originSpec,
|
||||||
&api.Pod{ObjectMeta: meta.ObjectMeta{UID: tc.podUID, Namespace: testns}},
|
&api.Pod{ObjectMeta: meta.ObjectMeta{UID: tc.podUID, Namespace: testns}},
|
||||||
@ -524,7 +554,7 @@ func TestPluginNewMounter(t *testing.T) {
|
|||||||
spec *volume.Spec
|
spec *volume.Spec
|
||||||
podUID types.UID
|
podUID types.UID
|
||||||
namespace string
|
namespace string
|
||||||
csiVolumeMode csiVolumeMode
|
volumeLifecycleMode storagev1beta1.VolumeLifecycleMode
|
||||||
shouldFail bool
|
shouldFail bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@ -532,14 +562,14 @@ func TestPluginNewMounter(t *testing.T) {
|
|||||||
spec: volume.NewSpecFromPersistentVolume(makeTestPV("test-pv1", 20, testDriver, testVol), true),
|
spec: volume.NewSpecFromPersistentVolume(makeTestPV("test-pv1", 20, testDriver, testVol), true),
|
||||||
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
||||||
namespace: "test-ns1",
|
namespace: "test-ns1",
|
||||||
csiVolumeMode: persistentVolumeMode,
|
volumeLifecycleMode: storagev1beta1.VolumeLifecyclePersistent,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "mounter from volume source",
|
name: "mounter from volume source",
|
||||||
spec: volume.NewSpecFromVolume(makeTestVol("test-vol1", testDriver)),
|
spec: volume.NewSpecFromVolume(makeTestVol("test-vol1", testDriver)),
|
||||||
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
||||||
namespace: "test-ns2",
|
namespace: "test-ns2",
|
||||||
csiVolumeMode: ephemeralVolumeMode,
|
volumeLifecycleMode: storagev1beta1.VolumeLifecycleEphemeral,
|
||||||
shouldFail: true, // csi inline not enabled
|
shouldFail: true, // csi inline not enabled
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -589,8 +619,8 @@ func TestPluginNewMounter(t *testing.T) {
|
|||||||
if csiClient == nil {
|
if csiClient == nil {
|
||||||
t.Error("mounter csiClient is nil")
|
t.Error("mounter csiClient is nil")
|
||||||
}
|
}
|
||||||
if csiMounter.csiVolumeMode != test.csiVolumeMode {
|
if csiMounter.volumeLifecycleMode != test.volumeLifecycleMode {
|
||||||
t.Error("unexpected driver mode:", csiMounter.csiVolumeMode)
|
t.Error("unexpected driver mode:", csiMounter.volumeLifecycleMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure data file is created
|
// ensure data file is created
|
||||||
@ -619,8 +649,8 @@ func TestPluginNewMounter(t *testing.T) {
|
|||||||
if data[volDataKey.nodeName] != string(csiMounter.plugin.host.GetNodeName()) {
|
if data[volDataKey.nodeName] != string(csiMounter.plugin.host.GetNodeName()) {
|
||||||
t.Error("volume data file unexpected nodeName:", data[volDataKey.nodeName])
|
t.Error("volume data file unexpected nodeName:", data[volDataKey.nodeName])
|
||||||
}
|
}
|
||||||
if data[volDataKey.csiVolumeMode] != string(test.csiVolumeMode) {
|
if data[volDataKey.volumeLifecycleMode] != string(test.volumeLifecycleMode) {
|
||||||
t.Error("volume data file unexpected csiVolumeMode:", data[volDataKey.csiVolumeMode])
|
t.Error("volume data file unexpected volumeLifecycleMode:", data[volDataKey.volumeLifecycleMode])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -629,12 +659,22 @@ func TestPluginNewMounter(t *testing.T) {
|
|||||||
func TestPluginNewMounterWithInline(t *testing.T) {
|
func TestPluginNewMounterWithInline(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
|
||||||
|
bothModes := []storagev1beta1.VolumeLifecycleMode{
|
||||||
|
storagev1beta1.VolumeLifecycleEphemeral,
|
||||||
|
storagev1beta1.VolumeLifecyclePersistent,
|
||||||
|
}
|
||||||
|
persistentMode := []storagev1beta1.VolumeLifecycleMode{
|
||||||
|
storagev1beta1.VolumeLifecyclePersistent,
|
||||||
|
}
|
||||||
|
ephemeralMode := []storagev1beta1.VolumeLifecycleMode{
|
||||||
|
storagev1beta1.VolumeLifecycleEphemeral,
|
||||||
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
spec *volume.Spec
|
spec *volume.Spec
|
||||||
podUID types.UID
|
podUID types.UID
|
||||||
namespace string
|
namespace string
|
||||||
csiVolumeMode csiVolumeMode
|
volumeLifecycleMode storagev1beta1.VolumeLifecycleMode
|
||||||
shouldFail bool
|
shouldFail bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@ -655,32 +695,43 @@ func TestPluginNewMounterWithInline(t *testing.T) {
|
|||||||
spec: volume.NewSpecFromPersistentVolume(makeTestPV("test-pv1", 20, testDriver, testVol), true),
|
spec: volume.NewSpecFromPersistentVolume(makeTestPV("test-pv1", 20, testDriver, testVol), true),
|
||||||
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
||||||
namespace: "test-ns1",
|
namespace: "test-ns1",
|
||||||
csiVolumeMode: persistentVolumeMode,
|
volumeLifecycleMode: storagev1beta1.VolumeLifecyclePersistent,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "mounter with volume source",
|
name: "mounter with volume source",
|
||||||
spec: volume.NewSpecFromVolume(makeTestVol("test-vol1", testDriver)),
|
spec: volume.NewSpecFromVolume(makeTestVol("test-vol1", testDriver)),
|
||||||
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
podUID: types.UID(fmt.Sprintf("%08X", rand.Uint64())),
|
||||||
namespace: "test-ns2",
|
namespace: "test-ns2",
|
||||||
csiVolumeMode: ephemeralVolumeMode,
|
volumeLifecycleMode: storagev1beta1.VolumeLifecycleEphemeral,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runAll := func(t *testing.T, supported []storagev1beta1.VolumeLifecycleMode) {
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
plug, tmpDir := newTestPlugin(t, nil)
|
driver := getTestCSIDriver(testDriver, nil, nil, supported)
|
||||||
|
fakeClient := fakeclient.NewSimpleClientset(driver)
|
||||||
|
plug, tmpDir := newTestPlugin(t, fakeClient)
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
registerFakePlugin(testDriver, "endpoint", []string{"1.2.0"}, t)
|
registerFakePlugin(testDriver, "endpoint", []string{"1.2.0"}, t)
|
||||||
|
|
||||||
mounter, err := plug.NewMounter(
|
mounter, err := plug.NewMounter(
|
||||||
test.spec,
|
test.spec,
|
||||||
&api.Pod{ObjectMeta: meta.ObjectMeta{UID: test.podUID, Namespace: test.namespace}},
|
&api.Pod{ObjectMeta: meta.ObjectMeta{UID: test.podUID, Namespace: test.namespace}},
|
||||||
volume.VolumeOptions{},
|
volume.VolumeOptions{},
|
||||||
)
|
)
|
||||||
if test.shouldFail != (err != nil) {
|
|
||||||
|
// Some test cases are meant to fail because their input data is broken.
|
||||||
|
shouldFail := test.shouldFail
|
||||||
|
// Others fail if the driver does not support the volume mode.
|
||||||
|
if !containsVolumeMode(supported, test.volumeLifecycleMode) {
|
||||||
|
shouldFail = true
|
||||||
|
}
|
||||||
|
if shouldFail != (err != nil) {
|
||||||
t.Fatal("Unexpected error:", err)
|
t.Fatal("Unexpected error:", err)
|
||||||
}
|
}
|
||||||
if test.shouldFail && err != nil {
|
if shouldFail && err != nil {
|
||||||
t.Log(err)
|
t.Log(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -707,8 +758,8 @@ func TestPluginNewMounterWithInline(t *testing.T) {
|
|||||||
if csiClient == nil {
|
if csiClient == nil {
|
||||||
t.Error("mounter csiClient is nil")
|
t.Error("mounter csiClient is nil")
|
||||||
}
|
}
|
||||||
if csiMounter.csiVolumeMode != test.csiVolumeMode {
|
if csiMounter.volumeLifecycleMode != test.volumeLifecycleMode {
|
||||||
t.Error("unexpected driver mode:", csiMounter.csiVolumeMode)
|
t.Error("unexpected driver mode:", csiMounter.volumeLifecycleMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure data file is created
|
// ensure data file is created
|
||||||
@ -737,11 +788,22 @@ func TestPluginNewMounterWithInline(t *testing.T) {
|
|||||||
if data[volDataKey.nodeName] != string(csiMounter.plugin.host.GetNodeName()) {
|
if data[volDataKey.nodeName] != string(csiMounter.plugin.host.GetNodeName()) {
|
||||||
t.Error("volume data file unexpected nodeName:", data[volDataKey.nodeName])
|
t.Error("volume data file unexpected nodeName:", data[volDataKey.nodeName])
|
||||||
}
|
}
|
||||||
if data[volDataKey.csiVolumeMode] != string(csiMounter.csiVolumeMode) {
|
if data[volDataKey.volumeLifecycleMode] != string(csiMounter.volumeLifecycleMode) {
|
||||||
t.Error("volume data file unexpected csiVolumeMode:", data[volDataKey.csiVolumeMode])
|
t.Error("volume data file unexpected volumeLifecycleMode:", data[volDataKey.volumeLifecycleMode])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("both supported", func(t *testing.T) {
|
||||||
|
runAll(t, bothModes)
|
||||||
|
})
|
||||||
|
t.Run("persistent supported", func(t *testing.T) {
|
||||||
|
runAll(t, persistentMode)
|
||||||
|
})
|
||||||
|
t.Run("ephemeral supported", func(t *testing.T) {
|
||||||
|
runAll(t, ephemeralMode)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPluginNewUnmounter(t *testing.T) {
|
func TestPluginNewUnmounter(t *testing.T) {
|
||||||
@ -871,8 +933,8 @@ func TestPluginCanAttach(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
csiDriver := getTestCSIDriver(test.driverName, nil, &test.canAttach)
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
csiDriver := getTestCSIDriver(test.driverName, nil, &test.canAttach, nil)
|
||||||
fakeCSIClient := fakeclient.NewSimpleClientset(csiDriver)
|
fakeCSIClient := fakeclient.NewSimpleClientset(csiDriver)
|
||||||
plug, tmpDir := newTestPlugin(t, fakeCSIClient)
|
plug, tmpDir := newTestPlugin(t, fakeCSIClient)
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
@ -932,7 +994,7 @@ func TestPluginFindAttachablePlugin(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
client := fakeclient.NewSimpleClientset(getTestCSIDriver(test.driverName, nil, &test.canAttach))
|
client := fakeclient.NewSimpleClientset(getTestCSIDriver(test.driverName, nil, &test.canAttach, nil))
|
||||||
factory := informers.NewSharedInformerFactory(client, CsiResyncPeriod)
|
factory := informers.NewSharedInformerFactory(client, CsiResyncPeriod)
|
||||||
host := volumetest.NewFakeVolumeHostWithCSINodeName(
|
host := volumetest.NewFakeVolumeHostWithCSINodeName(
|
||||||
tmpDir,
|
tmpDir,
|
||||||
|
@ -27,7 +27,10 @@ import (
|
|||||||
|
|
||||||
api "k8s.io/api/core/v1"
|
api "k8s.io/api/core/v1"
|
||||||
storage "k8s.io/api/storage/v1"
|
storage "k8s.io/api/storage/v1"
|
||||||
|
storagebeta1 "k8s.io/api/storage/v1beta1"
|
||||||
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
@ -45,6 +48,7 @@ import (
|
|||||||
// based on operations from the volume manager/reconciler/operation executor
|
// based on operations from the volume manager/reconciler/operation executor
|
||||||
func TestCSI_VolumeAll(t *testing.T) {
|
func TestCSI_VolumeAll(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
specName string
|
specName string
|
||||||
@ -54,6 +58,7 @@ func TestCSI_VolumeAll(t *testing.T) {
|
|||||||
podFunc func() *api.Pod
|
podFunc func() *api.Pod
|
||||||
isInline bool
|
isInline bool
|
||||||
shouldFail bool
|
shouldFail bool
|
||||||
|
driverSpec *storagebeta1.CSIDriverSpec
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "PersistentVolume",
|
name: "PersistentVolume",
|
||||||
@ -69,7 +74,42 @@ func TestCSI_VolumeAll(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ephermeral inline",
|
name: "PersistentVolume with driver info",
|
||||||
|
specName: "pv2",
|
||||||
|
driver: "simple-driver",
|
||||||
|
volName: "vol2",
|
||||||
|
specFunc: func(specName, driver, volName string) *volume.Spec {
|
||||||
|
return volume.NewSpecFromPersistentVolume(makeTestPV(specName, 20, driver, volName), false)
|
||||||
|
},
|
||||||
|
podFunc: func() *api.Pod {
|
||||||
|
podUID := types.UID(fmt.Sprintf("%08X", rand.Uint64()))
|
||||||
|
return &api.Pod{ObjectMeta: meta.ObjectMeta{UID: podUID, Namespace: testns}}
|
||||||
|
},
|
||||||
|
driverSpec: &storagebeta1.CSIDriverSpec{
|
||||||
|
// Required for the driver to be accepted for the persistent volume.
|
||||||
|
VolumeLifecycleModes: []storagebeta1.VolumeLifecycleMode{storagebeta1.VolumeLifecyclePersistent},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PersistentVolume with wrong mode in driver info",
|
||||||
|
specName: "pv2",
|
||||||
|
driver: "simple-driver",
|
||||||
|
volName: "vol2",
|
||||||
|
specFunc: func(specName, driver, volName string) *volume.Spec {
|
||||||
|
return volume.NewSpecFromPersistentVolume(makeTestPV(specName, 20, driver, volName), false)
|
||||||
|
},
|
||||||
|
podFunc: func() *api.Pod {
|
||||||
|
podUID := types.UID(fmt.Sprintf("%08X", rand.Uint64()))
|
||||||
|
return &api.Pod{ObjectMeta: meta.ObjectMeta{UID: podUID, Namespace: testns}}
|
||||||
|
},
|
||||||
|
driverSpec: &storagebeta1.CSIDriverSpec{
|
||||||
|
// This will cause the volume to be rejected.
|
||||||
|
VolumeLifecycleModes: []storagebeta1.VolumeLifecycleMode{storagebeta1.VolumeLifecycleEphemeral},
|
||||||
|
},
|
||||||
|
shouldFail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ephemeral inline supported",
|
||||||
driver: "inline-driver-1",
|
driver: "inline-driver-1",
|
||||||
volName: "test.vol2",
|
volName: "test.vol2",
|
||||||
specFunc: func(specName, driver, volName string) *volume.Spec {
|
specFunc: func(specName, driver, volName string) *volume.Spec {
|
||||||
@ -80,6 +120,75 @@ func TestCSI_VolumeAll(t *testing.T) {
|
|||||||
return &api.Pod{ObjectMeta: meta.ObjectMeta{UID: podUID, Namespace: testns}}
|
return &api.Pod{ObjectMeta: meta.ObjectMeta{UID: podUID, Namespace: testns}}
|
||||||
},
|
},
|
||||||
isInline: true,
|
isInline: true,
|
||||||
|
driverSpec: &storagebeta1.CSIDriverSpec{
|
||||||
|
// Required for the driver to be accepted for the inline volume.
|
||||||
|
VolumeLifecycleModes: []storagebeta1.VolumeLifecycleMode{storagebeta1.VolumeLifecycleEphemeral},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ephemeral inline also supported",
|
||||||
|
driver: "inline-driver-1",
|
||||||
|
volName: "test.vol2",
|
||||||
|
specFunc: func(specName, driver, volName string) *volume.Spec {
|
||||||
|
return volume.NewSpecFromVolume(makeTestVol(specName, driver))
|
||||||
|
},
|
||||||
|
podFunc: func() *api.Pod {
|
||||||
|
podUID := types.UID(fmt.Sprintf("%08X", rand.Uint64()))
|
||||||
|
return &api.Pod{ObjectMeta: meta.ObjectMeta{UID: podUID, Namespace: testns}}
|
||||||
|
},
|
||||||
|
isInline: true,
|
||||||
|
driverSpec: &storagebeta1.CSIDriverSpec{
|
||||||
|
// Required for the driver to be accepted for the inline volume.
|
||||||
|
VolumeLifecycleModes: []storagebeta1.VolumeLifecycleMode{storagebeta1.VolumeLifecyclePersistent, storagebeta1.VolumeLifecycleEphemeral},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ephemeral inline without CSIDriver info",
|
||||||
|
driver: "inline-driver-2",
|
||||||
|
volName: "test.vol3",
|
||||||
|
specFunc: func(specName, driver, volName string) *volume.Spec {
|
||||||
|
return volume.NewSpecFromVolume(makeTestVol(specName, driver))
|
||||||
|
},
|
||||||
|
podFunc: func() *api.Pod {
|
||||||
|
podUID := types.UID(fmt.Sprintf("%08X", rand.Uint64()))
|
||||||
|
return &api.Pod{ObjectMeta: meta.ObjectMeta{UID: podUID, Namespace: testns}}
|
||||||
|
},
|
||||||
|
isInline: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ephemeral inline with driver that has no mode",
|
||||||
|
driver: "inline-driver-3",
|
||||||
|
volName: "test.vol4",
|
||||||
|
specFunc: func(specName, driver, volName string) *volume.Spec {
|
||||||
|
return volume.NewSpecFromVolume(makeTestVol(specName, driver))
|
||||||
|
},
|
||||||
|
podFunc: func() *api.Pod {
|
||||||
|
podUID := types.UID(fmt.Sprintf("%08X", rand.Uint64()))
|
||||||
|
return &api.Pod{ObjectMeta: meta.ObjectMeta{UID: podUID, Namespace: testns}}
|
||||||
|
},
|
||||||
|
isInline: true,
|
||||||
|
driverSpec: &storagebeta1.CSIDriverSpec{
|
||||||
|
// This means the driver *cannot* handle the inline volume because
|
||||||
|
// the default is "persistent".
|
||||||
|
VolumeLifecycleModes: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ephemeral inline with driver that has wrong mode",
|
||||||
|
driver: "inline-driver-3",
|
||||||
|
volName: "test.vol4",
|
||||||
|
specFunc: func(specName, driver, volName string) *volume.Spec {
|
||||||
|
return volume.NewSpecFromVolume(makeTestVol(specName, driver))
|
||||||
|
},
|
||||||
|
podFunc: func() *api.Pod {
|
||||||
|
podUID := types.UID(fmt.Sprintf("%08X", rand.Uint64()))
|
||||||
|
return &api.Pod{ObjectMeta: meta.ObjectMeta{UID: podUID, Namespace: testns}}
|
||||||
|
},
|
||||||
|
isInline: true,
|
||||||
|
driverSpec: &storagebeta1.CSIDriverSpec{
|
||||||
|
// This means the driver *cannot* handle the inline volume.
|
||||||
|
VolumeLifecycleModes: []storagebeta1.VolumeLifecycleMode{storagebeta1.VolumeLifecyclePersistent},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "missing spec",
|
name: "missing spec",
|
||||||
@ -118,10 +227,27 @@ func TestCSI_VolumeAll(t *testing.T) {
|
|||||||
t.Fatalf("can't create temp dir: %v", err)
|
t.Fatalf("can't create temp dir: %v", err)
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
client := fakeclient.NewSimpleClientset()
|
|
||||||
|
var driverInfo *storagebeta1.CSIDriver
|
||||||
|
objs := []runtime.Object{}
|
||||||
|
if test.driverSpec != nil {
|
||||||
|
driverInfo = &storagebeta1.CSIDriver{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: test.driver,
|
||||||
|
},
|
||||||
|
Spec: *test.driverSpec,
|
||||||
|
}
|
||||||
|
objs = append(objs, driverInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
client := fakeclient.NewSimpleClientset(objs...)
|
||||||
fakeWatcher := watch.NewRaceFreeFake()
|
fakeWatcher := watch.NewRaceFreeFake()
|
||||||
|
|
||||||
factory := informers.NewSharedInformerFactory(client, CsiResyncPeriod)
|
factory := informers.NewSharedInformerFactory(client, time.Hour /* disable resync */)
|
||||||
|
csiDriverInformer := factory.Storage().V1beta1().CSIDrivers()
|
||||||
|
if driverInfo != nil {
|
||||||
|
csiDriverInformer.Informer().GetStore().Add(driverInfo)
|
||||||
|
}
|
||||||
factory.Start(wait.NeverStop)
|
factory.Start(wait.NeverStop)
|
||||||
|
|
||||||
host := volumetest.NewFakeVolumeHostWithCSINodeName(
|
host := volumetest.NewFakeVolumeHostWithCSINodeName(
|
||||||
@ -129,7 +255,7 @@ func TestCSI_VolumeAll(t *testing.T) {
|
|||||||
client,
|
client,
|
||||||
nil,
|
nil,
|
||||||
"csi-node",
|
"csi-node",
|
||||||
factory.Storage().V1beta1().CSIDrivers().Lister(),
|
csiDriverInformer.Lister(),
|
||||||
)
|
)
|
||||||
|
|
||||||
plugMgr := &volume.VolumePluginMgr{}
|
plugMgr := &volume.VolumePluginMgr{}
|
||||||
@ -253,6 +379,22 @@ func TestCSI_VolumeAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mounter, err := volPlug.NewMounter(volSpec, pod, volume.VolumeOptions{})
|
mounter, err := volPlug.NewMounter(volSpec, pod, volume.VolumeOptions{})
|
||||||
|
if test.isInline && (test.driverSpec == nil || !containsVolumeMode(test.driverSpec.VolumeLifecycleModes, storagebeta1.VolumeLifecycleEphemeral)) {
|
||||||
|
// This *must* fail because a CSIDriver.Spec.VolumeLifecycleModes entry "ephemeral"
|
||||||
|
// is required.
|
||||||
|
if err == nil || mounter != nil {
|
||||||
|
t.Fatalf("csiTest.VolumeAll volPlugin.NewMounter should have failed for inline volume due to lack of support for inline volumes, got: %+v, %s", mounter, err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !test.isInline && test.driverSpec != nil && !containsVolumeMode(test.driverSpec.VolumeLifecycleModes, storagebeta1.VolumeLifecyclePersistent) {
|
||||||
|
// This *must* fail because a CSIDriver.Spec.VolumeLifecycleModes entry "persistent"
|
||||||
|
// is required when a driver object is available.
|
||||||
|
if err == nil || mounter != nil {
|
||||||
|
t.Fatalf("csiTest.VolumeAll volPlugin.NewMounter should have failed for persistent volume due to lack of support for persistent volumes, got: %+v, %s", mounter, err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
if err != nil || mounter == nil {
|
if err != nil || mounter == nil {
|
||||||
t.Fatalf("csiTest.VolumeAll volPlugin.NewMounter is nil or error: %s", err)
|
t.Fatalf("csiTest.VolumeAll volPlugin.NewMounter is nil or error: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ func makeTestVol(name string, driverName string) *api.Volume {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTestCSIDriver(name string, podInfoMount *bool, attachable *bool) *storagev1beta1.CSIDriver {
|
func getTestCSIDriver(name string, podInfoMount *bool, attachable *bool, volumeLifecycleModes []storagev1beta1.VolumeLifecycleMode) *storagev1beta1.CSIDriver {
|
||||||
return &storagev1beta1.CSIDriver{
|
return &storagev1beta1.CSIDriver{
|
||||||
ObjectMeta: meta.ObjectMeta{
|
ObjectMeta: meta.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
@ -92,6 +92,7 @@ func getTestCSIDriver(name string, podInfoMount *bool, attachable *bool) *storag
|
|||||||
Spec: storagev1beta1.CSIDriverSpec{
|
Spec: storagev1beta1.CSIDriverSpec{
|
||||||
PodInfoOnMount: podInfoMount,
|
PodInfoOnMount: podInfoMount,
|
||||||
AttachRequired: attachable,
|
AttachRequired: attachable,
|
||||||
|
VolumeLifecycleModes: volumeLifecycleModes,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
216
staging/src/k8s.io/api/storage/v1beta1/generated.pb.go
generated
216
staging/src/k8s.io/api/storage/v1beta1/generated.pb.go
generated
@ -520,89 +520,91 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var fileDescriptor_7d2980599fd0de80 = []byte{
|
var fileDescriptor_7d2980599fd0de80 = []byte{
|
||||||
// 1311 bytes of a gzipped FileDescriptorProto
|
// 1344 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x4d, 0x6f, 0x1b, 0x45,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0xbd, 0x6f, 0xdb, 0x46,
|
||||||
0x18, 0xce, 0xc6, 0xf9, 0x1c, 0x27, 0xad, 0x33, 0x8d, 0xc0, 0xf8, 0x60, 0x47, 0x46, 0xd0, 0xb4,
|
0x1b, 0x37, 0x2d, 0x7f, 0x9e, 0xec, 0x44, 0xbe, 0x18, 0xef, 0xab, 0x57, 0x83, 0x64, 0xe8, 0x45,
|
||||||
0x6a, 0xd7, 0x6d, 0x55, 0xaa, 0xaa, 0x12, 0x87, 0x6c, 0x1a, 0x09, 0xb7, 0x75, 0x1a, 0x26, 0x51,
|
0x1b, 0x27, 0x48, 0xc8, 0x24, 0x48, 0x83, 0x20, 0x40, 0x07, 0xd3, 0x31, 0x50, 0x25, 0x96, 0xe3,
|
||||||
0x85, 0x2a, 0x0e, 0x8c, 0x77, 0xdf, 0x3a, 0xdb, 0x78, 0x77, 0xb6, 0x33, 0x63, 0x43, 0x6e, 0x9c,
|
0x9e, 0x8d, 0xa0, 0x08, 0x3a, 0xf4, 0x44, 0x3e, 0x91, 0x19, 0x93, 0x3c, 0x86, 0x3c, 0xa9, 0xd5,
|
||||||
0xe0, 0x8a, 0x38, 0xf0, 0x0b, 0xf8, 0x0b, 0x20, 0xc1, 0x85, 0x23, 0x3d, 0xa1, 0x8a, 0x53, 0x4f,
|
0xd6, 0xa9, 0x73, 0xd1, 0xa1, 0x7f, 0x41, 0xff, 0x85, 0x16, 0x68, 0x97, 0x8e, 0xcd, 0x54, 0x04,
|
||||||
0x16, 0x5d, 0x7e, 0x02, 0xb7, 0x88, 0x03, 0x9a, 0xd9, 0x89, 0x77, 0xfd, 0xd5, 0x24, 0x1c, 0x72,
|
0x9d, 0x32, 0x09, 0x0d, 0xbb, 0x76, 0xeb, 0x66, 0x74, 0x28, 0xee, 0x78, 0x12, 0x29, 0x89, 0x8a,
|
||||||
0xf3, 0xbc, 0x1f, 0xcf, 0xfb, 0xf5, 0xcc, 0x3b, 0x6b, 0xb4, 0x79, 0x70, 0x57, 0xd8, 0x3e, 0xab,
|
0xed, 0x0e, 0xde, 0x78, 0xcf, 0xc7, 0xef, 0xf9, 0x7e, 0xee, 0x88, 0xb6, 0x8f, 0xef, 0x47, 0xba,
|
||||||
0x1d, 0x74, 0x9a, 0xc0, 0x43, 0x90, 0x20, 0x6a, 0x5d, 0x08, 0x3d, 0xc6, 0x6b, 0x46, 0x41, 0x23,
|
0xc3, 0x8c, 0xe3, 0x4e, 0x0b, 0x42, 0x1f, 0x38, 0x44, 0x46, 0x17, 0x7c, 0x9b, 0x85, 0x86, 0x62,
|
||||||
0xbf, 0x26, 0x24, 0xe3, 0xb4, 0x05, 0xb5, 0xee, 0xcd, 0x26, 0x48, 0x7a, 0xb3, 0xd6, 0x82, 0x10,
|
0xd0, 0xc0, 0x31, 0x22, 0xce, 0x42, 0xda, 0x06, 0xa3, 0x7b, 0xbb, 0x05, 0x9c, 0xde, 0x36, 0xda,
|
||||||
0x38, 0x95, 0xe0, 0xd9, 0x11, 0x67, 0x92, 0xe1, 0x52, 0x62, 0x6b, 0xd3, 0xc8, 0xb7, 0x8d, 0xad,
|
0xe0, 0x43, 0x48, 0x39, 0xd8, 0x7a, 0x10, 0x32, 0xce, 0x70, 0x25, 0x91, 0xd5, 0x69, 0xe0, 0xe8,
|
||||||
0x6d, 0x6c, 0x4b, 0xd7, 0x5b, 0xbe, 0xdc, 0xef, 0x34, 0x6d, 0x97, 0x05, 0xb5, 0x16, 0x6b, 0xb1,
|
0x4a, 0x56, 0x57, 0xb2, 0x95, 0x9b, 0x6d, 0x87, 0x1f, 0x75, 0x5a, 0xba, 0xc5, 0x3c, 0xa3, 0xcd,
|
||||||
0x9a, 0x76, 0x69, 0x76, 0x9e, 0xe9, 0x93, 0x3e, 0xe8, 0x5f, 0x09, 0x54, 0xa9, 0x9a, 0x09, 0xeb,
|
0xda, 0xcc, 0x90, 0x2a, 0xad, 0xce, 0x73, 0x79, 0x92, 0x07, 0xf9, 0x95, 0x40, 0x55, 0xea, 0x19,
|
||||||
0x32, 0xae, 0x62, 0x0e, 0x87, 0x2b, 0xdd, 0x4e, 0x6d, 0x02, 0xea, 0xee, 0xfb, 0x21, 0xf0, 0xc3,
|
0xb3, 0x16, 0x0b, 0x85, 0xcd, 0x71, 0x73, 0x95, 0xbb, 0xa9, 0x8c, 0x47, 0xad, 0x23, 0xc7, 0x87,
|
||||||
0x5a, 0x74, 0xd0, 0x52, 0x02, 0x51, 0x0b, 0x40, 0xd2, 0x71, 0x5e, 0xb5, 0x49, 0x5e, 0xbc, 0x13,
|
0xb0, 0x67, 0x04, 0xc7, 0x6d, 0x41, 0x88, 0x0c, 0x0f, 0x38, 0xcd, 0xd3, 0x32, 0xa6, 0x69, 0x85,
|
||||||
0x4a, 0x3f, 0x80, 0x11, 0x87, 0x3b, 0x27, 0x39, 0x08, 0x77, 0x1f, 0x02, 0x3a, 0xec, 0x57, 0xfd,
|
0x1d, 0x9f, 0x3b, 0x1e, 0x4c, 0x28, 0xdc, 0x3b, 0x4d, 0x21, 0xb2, 0x8e, 0xc0, 0xa3, 0xe3, 0x7a,
|
||||||
0xd5, 0x42, 0x8b, 0x9b, 0xbb, 0xf5, 0xfb, 0xdc, 0xef, 0x02, 0xc7, 0x5f, 0xa0, 0x05, 0x95, 0x91,
|
0xf5, 0x9f, 0x34, 0xb4, 0xbc, 0x7d, 0xd0, 0x78, 0x18, 0x3a, 0x5d, 0x08, 0xf1, 0x67, 0x68, 0x49,
|
||||||
0x47, 0x25, 0x2d, 0x5a, 0x6b, 0xd6, 0x7a, 0xfe, 0xd6, 0x0d, 0x3b, 0x6d, 0x57, 0x1f, 0xd8, 0x8e,
|
0x78, 0x64, 0x53, 0x4e, 0xcb, 0xda, 0x86, 0xb6, 0x59, 0xbc, 0x73, 0x4b, 0x4f, 0xd3, 0x35, 0x04,
|
||||||
0x0e, 0x5a, 0x4a, 0x20, 0x6c, 0x65, 0x6d, 0x77, 0x6f, 0xda, 0x8f, 0x9b, 0xcf, 0xc1, 0x95, 0x0d,
|
0xd6, 0x83, 0xe3, 0xb6, 0x20, 0x44, 0xba, 0x90, 0xd6, 0xbb, 0xb7, 0xf5, 0x27, 0xad, 0x17, 0x60,
|
||||||
0x90, 0xd4, 0xc1, 0x2f, 0x7b, 0x95, 0xa9, 0xb8, 0x57, 0x41, 0xa9, 0x8c, 0xf4, 0x51, 0xf1, 0x43,
|
0xf1, 0x26, 0x70, 0x6a, 0xe2, 0x57, 0xfd, 0xda, 0x4c, 0xdc, 0xaf, 0xa1, 0x94, 0x46, 0x86, 0xa8,
|
||||||
0x34, 0x23, 0x22, 0x70, 0x8b, 0xd3, 0x1a, 0xfd, 0x8a, 0x3d, 0x79, 0x18, 0x76, 0x3f, 0xad, 0xdd,
|
0xf8, 0x31, 0x9a, 0x8b, 0x02, 0xb0, 0xca, 0xb3, 0x12, 0xfd, 0x9a, 0x3e, 0xbd, 0x18, 0xfa, 0xd0,
|
||||||
0x08, 0x5c, 0x67, 0xc9, 0xc0, 0xce, 0xa8, 0x13, 0xd1, 0x20, 0xd5, 0x5f, 0x2c, 0xb4, 0xdc, 0xb7,
|
0xad, 0x83, 0x00, 0x2c, 0x73, 0x45, 0xc1, 0xce, 0x89, 0x13, 0x91, 0x20, 0xf5, 0x1f, 0x35, 0xb4,
|
||||||
0x7a, 0xe4, 0x0b, 0x89, 0x3f, 0x1f, 0x29, 0xc0, 0x3e, 0x5d, 0x01, 0xca, 0x5b, 0xa7, 0x5f, 0x30,
|
0x3a, 0x94, 0xda, 0x75, 0x22, 0x8e, 0x3f, 0x9d, 0x08, 0x40, 0x3f, 0x5b, 0x00, 0x42, 0x5b, 0xba,
|
||||||
0x71, 0x16, 0x8e, 0x25, 0x99, 0xe4, 0x1f, 0xa0, 0x59, 0x5f, 0x42, 0x20, 0x8a, 0xd3, 0x6b, 0xb9,
|
0x5f, 0x52, 0x76, 0x96, 0x06, 0x94, 0x8c, 0xf3, 0x8f, 0xd0, 0xbc, 0xc3, 0xc1, 0x8b, 0xca, 0xb3,
|
||||||
0xf5, 0xfc, 0xad, 0x0f, 0x4e, 0x95, 0xbd, 0xb3, 0x6c, 0x10, 0x67, 0xeb, 0xca, 0x97, 0x24, 0x10,
|
0x1b, 0x85, 0xcd, 0xe2, 0x9d, 0xf7, 0xce, 0xe4, 0xbd, 0xb9, 0xaa, 0x10, 0xe7, 0x1b, 0x42, 0x97,
|
||||||
0xd5, 0x6f, 0xb3, 0xb9, 0xab, 0x9a, 0xf0, 0x3d, 0x74, 0x81, 0x4a, 0x49, 0xdd, 0x7d, 0x02, 0x2f,
|
0x24, 0x10, 0xf5, 0x3f, 0xb3, 0xbe, 0x8b, 0x98, 0xf0, 0x03, 0x74, 0x89, 0x72, 0x4e, 0xad, 0x23,
|
||||||
0x3a, 0x3e, 0x07, 0x4f, 0x57, 0xb0, 0xe0, 0xe0, 0xb8, 0x57, 0xb9, 0xb0, 0x31, 0xa0, 0x21, 0x43,
|
0x02, 0x2f, 0x3b, 0x4e, 0x08, 0xb6, 0x8c, 0x60, 0xc9, 0xc4, 0x71, 0xbf, 0x76, 0x69, 0x6b, 0x84,
|
||||||
0x96, 0xca, 0x37, 0x62, 0x5e, 0x3d, 0x7c, 0xc6, 0x1e, 0x87, 0x0d, 0xd6, 0x09, 0xa5, 0x6e, 0xb0,
|
0x43, 0xc6, 0x24, 0x85, 0x6e, 0xc0, 0xec, 0x86, 0xff, 0x9c, 0x3d, 0xf1, 0x9b, 0xac, 0xe3, 0x73,
|
||||||
0xf1, 0xdd, 0x19, 0xd0, 0x90, 0x21, 0xcb, 0xea, 0xcf, 0x16, 0x9a, 0xdf, 0xdc, 0xad, 0x6f, 0x33,
|
0x99, 0x60, 0xa5, 0xbb, 0x3f, 0xc2, 0x21, 0x63, 0x92, 0xd8, 0x42, 0xeb, 0x5d, 0xe6, 0x76, 0x3c,
|
||||||
0x0f, 0xce, 0x81, 0x00, 0xf5, 0x01, 0x02, 0x5c, 0x3e, 0xa1, 0x85, 0x2a, 0xa9, 0x89, 0xe3, 0xff,
|
0xd8, 0x75, 0x9e, 0x83, 0xd5, 0xb3, 0x5c, 0x68, 0x32, 0x1b, 0xa2, 0x72, 0x61, 0xa3, 0xb0, 0xb9,
|
||||||
0x27, 0x69, 0xa1, 0xb2, 0x31, 0xfc, 0x5d, 0x43, 0x33, 0x21, 0x0d, 0x40, 0xa7, 0xbe, 0x98, 0xfa,
|
0x6c, 0x1a, 0x71, 0xbf, 0xb6, 0xfe, 0x34, 0x87, 0x7f, 0xd2, 0xaf, 0x5d, 0xc9, 0xa1, 0x93, 0x5c,
|
||||||
0x6c, 0xd3, 0x00, 0x88, 0xd6, 0xe0, 0x0f, 0xd1, 0x5c, 0xc8, 0x3c, 0xa8, 0xdf, 0xd7, 0x09, 0x2c,
|
0xb0, 0xfa, 0x0f, 0x1a, 0x5a, 0xdc, 0x3e, 0x68, 0xec, 0x31, 0x1b, 0x2e, 0xa0, 0xcb, 0x1a, 0x23,
|
||||||
0x3a, 0x17, 0x8c, 0xcd, 0xdc, 0xb6, 0x96, 0x12, 0xa3, 0xc5, 0xb7, 0xd1, 0x92, 0x64, 0x11, 0x6b,
|
0x5d, 0x76, 0xf5, 0x94, 0x3a, 0x09, 0xa7, 0xa6, 0xf6, 0xd8, 0x5f, 0x49, 0x9d, 0x84, 0x8c, 0x1a,
|
||||||
0xb3, 0xd6, 0xe1, 0x43, 0x38, 0x14, 0xc5, 0xdc, 0x5a, 0x6e, 0x7d, 0xd1, 0x29, 0xc4, 0xbd, 0xca,
|
0x92, 0x0d, 0x34, 0xe7, 0x53, 0x0f, 0xa4, 0xeb, 0xcb, 0xa9, 0xce, 0x1e, 0xf5, 0x80, 0x48, 0x0e,
|
||||||
0xd2, 0x5e, 0x46, 0x4e, 0x06, 0xac, 0x70, 0x13, 0xe5, 0x69, 0xbb, 0xcd, 0x5c, 0x2a, 0x69, 0xb3,
|
0x7e, 0x1f, 0x2d, 0xf8, 0xcc, 0x86, 0xc6, 0x43, 0xe9, 0xc0, 0xb2, 0x79, 0x49, 0xc9, 0x2c, 0xec,
|
||||||
0x0d, 0xc5, 0x19, 0x5d, 0x63, 0xed, 0x6d, 0x35, 0x3e, 0x61, 0xed, 0x4e, 0x00, 0x2a, 0x38, 0x01,
|
0x49, 0x2a, 0x51, 0x5c, 0x7c, 0x17, 0xad, 0x70, 0x16, 0x30, 0x97, 0xb5, 0x7b, 0x8f, 0xa1, 0x37,
|
||||||
0xc1, 0x3a, 0xdc, 0x05, 0xe1, 0x5c, 0x8c, 0x7b, 0x95, 0xfc, 0x46, 0x8a, 0x43, 0xb2, 0xa0, 0xd5,
|
0xc8, 0x78, 0x29, 0xee, 0xd7, 0x56, 0x0e, 0x33, 0x74, 0x32, 0x22, 0x85, 0x5b, 0xa8, 0x48, 0x5d,
|
||||||
0x9f, 0x2c, 0x94, 0x37, 0x55, 0x9f, 0x03, 0xe5, 0x3f, 0x19, 0xa4, 0xfc, 0xfb, 0xa7, 0x98, 0xd7,
|
0x97, 0x59, 0x94, 0xd3, 0x96, 0x0b, 0xe5, 0x39, 0x19, 0xa3, 0xf1, 0xae, 0x18, 0x93, 0x32, 0x09,
|
||||||
0x04, 0xc2, 0xbb, 0xfd, 0xb4, 0x35, 0xdb, 0xf7, 0xd0, 0xbc, 0xa7, 0x87, 0x26, 0x8a, 0x96, 0x86,
|
0xe3, 0x04, 0x22, 0xd6, 0x09, 0x2d, 0x88, 0xcc, 0xcb, 0x71, 0xbf, 0x56, 0xdc, 0x4a, 0x71, 0x48,
|
||||||
0xbe, 0x72, 0x0a, 0x68, 0x73, 0xa3, 0x2e, 0x9a, 0x00, 0xf3, 0xc9, 0x59, 0x90, 0x63, 0xa8, 0xea,
|
0x16, 0xb4, 0xfe, 0xbd, 0x86, 0x8a, 0x2a, 0xea, 0x0b, 0x98, 0xab, 0x8f, 0x46, 0xe7, 0xea, 0xff,
|
||||||
0xf7, 0x73, 0x68, 0x69, 0x37, 0xf1, 0xdd, 0x6c, 0x53, 0x21, 0xce, 0x81, 0xd0, 0x1f, 0xa1, 0x7c,
|
0x67, 0xa8, 0xd7, 0x94, 0xa9, 0xb2, 0x86, 0x6e, 0xcb, 0x91, 0x3a, 0x44, 0x8b, 0xb6, 0x2c, 0x5a,
|
||||||
0xc4, 0x59, 0xd7, 0x17, 0x3e, 0x0b, 0x81, 0x1b, 0x5a, 0x5d, 0x32, 0x2e, 0xf9, 0x9d, 0x54, 0x45,
|
0x54, 0xd6, 0x24, 0xf4, 0xb5, 0x33, 0x40, 0xab, 0xb1, 0xbd, 0xac, 0x0c, 0x2c, 0x26, 0xe7, 0x88,
|
||||||
0xb2, 0x76, 0xb8, 0x8d, 0x50, 0x44, 0x39, 0x0d, 0x40, 0xaa, 0x16, 0xe4, 0x74, 0x0b, 0xee, 0xbe,
|
0x0c, 0xa0, 0xea, 0xdf, 0x2c, 0xa0, 0x95, 0x83, 0x44, 0x77, 0xdb, 0xa5, 0x51, 0x74, 0x01, 0x0d,
|
||||||
0xad, 0x05, 0xd9, 0xb2, 0xec, 0x9d, 0xbe, 0xeb, 0x56, 0x28, 0xf9, 0x61, 0x9a, 0x62, 0xaa, 0x20,
|
0xfd, 0x01, 0x2a, 0x06, 0x21, 0xeb, 0x3a, 0x91, 0xc3, 0x7c, 0x08, 0x55, 0x5b, 0x5d, 0x51, 0x2a,
|
||||||
0x19, 0x7c, 0x7c, 0x80, 0x96, 0x39, 0xb8, 0x6d, 0xea, 0x07, 0x3b, 0xac, 0xed, 0xbb, 0x87, 0x9a,
|
0xc5, 0xfd, 0x94, 0x45, 0xb2, 0x72, 0xd8, 0x45, 0x28, 0xa0, 0x21, 0xf5, 0x80, 0x8b, 0x14, 0x14,
|
||||||
0x9a, 0x8b, 0xce, 0x56, 0xdc, 0xab, 0x2c, 0x93, 0xac, 0xe2, 0xa8, 0x57, 0xb9, 0x31, 0xfa, 0xaa,
|
0x64, 0x0a, 0xee, 0xbf, 0x2b, 0x05, 0xd9, 0xb0, 0xf4, 0xfd, 0xa1, 0xea, 0x8e, 0xcf, 0xc3, 0x5e,
|
||||||
0xd9, 0x3b, 0xc0, 0x85, 0x2f, 0x24, 0x84, 0x32, 0x21, 0xec, 0x80, 0x0f, 0x19, 0xc4, 0x56, 0x77,
|
0xea, 0x62, 0xca, 0x20, 0x19, 0x7c, 0x7c, 0x8c, 0x56, 0x43, 0xb0, 0x5c, 0xea, 0x78, 0xfb, 0xcc,
|
||||||
0x27, 0x50, 0x9b, 0xe5, 0x71, 0x24, 0x7d, 0x16, 0x8a, 0xe2, 0x6c, 0x7a, 0x77, 0x1a, 0x19, 0x39,
|
0x75, 0xac, 0x9e, 0x6c, 0xcd, 0x65, 0x73, 0x27, 0xee, 0xd7, 0x56, 0x49, 0x96, 0x71, 0xd2, 0xaf,
|
||||||
0x19, 0xb0, 0xc2, 0x8f, 0xd0, 0xaa, 0xa2, 0xf9, 0x97, 0x49, 0x80, 0xad, 0xaf, 0x22, 0x1a, 0xaa,
|
0xdd, 0x9a, 0xbc, 0x3a, 0xf5, 0x7d, 0x08, 0x23, 0x27, 0xe2, 0xe0, 0xf3, 0xa4, 0x61, 0x47, 0x74,
|
||||||
0x56, 0x15, 0xe7, 0xf4, 0x22, 0x2b, 0xc6, 0xbd, 0xca, 0xea, 0xc6, 0x18, 0x3d, 0x19, 0xeb, 0x85,
|
0xc8, 0x28, 0xb6, 0x98, 0x1d, 0x4f, 0xac, 0xaf, 0x27, 0x01, 0x77, 0x98, 0x1f, 0x95, 0xe7, 0xd3,
|
||||||
0x3f, 0x43, 0x2b, 0x5d, 0x2d, 0x72, 0xfc, 0xd0, 0xf3, 0xc3, 0x56, 0x83, 0x79, 0x50, 0x9c, 0xd7,
|
0xd9, 0x69, 0x66, 0xe8, 0x64, 0x44, 0x0a, 0xef, 0xa2, 0x75, 0xd1, 0xe6, 0x9f, 0x27, 0x06, 0x76,
|
||||||
0x45, 0x5f, 0x8d, 0x7b, 0x95, 0x95, 0x27, 0xc3, 0xca, 0xa3, 0x71, 0x42, 0x32, 0x0a, 0x82, 0x5f,
|
0xbe, 0x08, 0xa8, 0x2f, 0x52, 0x55, 0x5e, 0x90, 0xdb, 0xb2, 0x2c, 0x76, 0xdd, 0x56, 0x0e, 0x9f,
|
||||||
0xa0, 0x15, 0x1d, 0x11, 0x3c, 0xb3, 0x08, 0x7c, 0x10, 0xc5, 0x05, 0x3d, 0xbf, 0xf5, 0xec, 0xfc,
|
0xe4, 0x6a, 0xe1, 0x4f, 0xd0, 0x5a, 0xb2, 0xec, 0x4c, 0xc7, 0xb7, 0x1d, 0xbf, 0x2d, 0x56, 0x5d,
|
||||||
0x54, 0xeb, 0x14, 0x91, 0x8e, 0xd7, 0xc5, 0x2e, 0xb4, 0xc1, 0x95, 0x8c, 0xef, 0x01, 0x0f, 0x9c,
|
0x79, 0x51, 0x06, 0x7d, 0x3d, 0xee, 0xd7, 0xd6, 0x9e, 0x8e, 0x33, 0x4f, 0xf2, 0x88, 0x64, 0x12,
|
||||||
0xf7, 0xcc, 0xbc, 0x56, 0x36, 0x86, 0xa1, 0xc8, 0x28, 0x7a, 0xe9, 0x63, 0x74, 0x71, 0x68, 0xe0,
|
0x04, 0xbf, 0x44, 0x6b, 0xd2, 0x22, 0xd8, 0x6a, 0x11, 0x38, 0x10, 0x95, 0x97, 0x64, 0xfd, 0x36,
|
||||||
0xb8, 0x80, 0x72, 0x07, 0x70, 0x98, 0x2c, 0x3a, 0xa2, 0x7e, 0xe2, 0x55, 0x34, 0xdb, 0xa5, 0xed,
|
0xb3, 0xf5, 0x13, 0xa9, 0x13, 0x8d, 0x34, 0x58, 0x17, 0x07, 0xe0, 0x82, 0xc5, 0x59, 0x78, 0x08,
|
||||||
0x0e, 0x24, 0x0c, 0x24, 0xc9, 0xe1, 0xde, 0xf4, 0x5d, 0xab, 0xfa, 0x9b, 0x85, 0x0a, 0x59, 0xf6,
|
0xa1, 0x67, 0xfe, 0x4f, 0xd5, 0x6b, 0x6d, 0x6b, 0x1c, 0x8a, 0x4c, 0xa2, 0x57, 0x3e, 0x44, 0x97,
|
||||||
0x9c, 0xc3, 0xda, 0x68, 0x0c, 0xae, 0x8d, 0xf5, 0xd3, 0x12, 0x7b, 0xc2, 0xee, 0xf8, 0x71, 0x1a,
|
0xc7, 0x0a, 0x8e, 0x4b, 0xa8, 0x70, 0x0c, 0xbd, 0x64, 0xd1, 0x11, 0xf1, 0x89, 0xd7, 0xd1, 0x7c,
|
||||||
0x15, 0x92, 0xe1, 0x24, 0xef, 0x60, 0x00, 0xa1, 0x3c, 0x87, 0xab, 0x4d, 0x06, 0xde, 0xaa, 0x1b,
|
0x97, 0xba, 0x1d, 0x48, 0x3a, 0x90, 0x24, 0x87, 0x07, 0xb3, 0xf7, 0xb5, 0xfa, 0xcf, 0x1a, 0x2a,
|
||||||
0x27, 0xef, 0xf1, 0x34, 0xbb, 0x49, 0x8f, 0x16, 0x7e, 0x8a, 0xe6, 0x84, 0xa4, 0xb2, 0xa3, 0xee,
|
0x65, 0xbb, 0xe7, 0x02, 0xd6, 0x46, 0x73, 0x74, 0x6d, 0x6c, 0x9e, 0xb5, 0xb1, 0xa7, 0xec, 0x8e,
|
||||||
0xbc, 0x42, 0xbd, 0x75, 0x26, 0x54, 0xed, 0x99, 0x3e, 0x5a, 0xc9, 0x99, 0x18, 0xc4, 0xea, 0xef,
|
0xef, 0x66, 0x51, 0x29, 0x29, 0x4e, 0x72, 0xd9, 0x7a, 0xe0, 0xf3, 0x0b, 0x18, 0x6d, 0x32, 0x72,
|
||||||
0x16, 0x5a, 0x1d, 0x76, 0x39, 0x87, 0x61, 0x7f, 0x3a, 0x38, 0xec, 0x6b, 0x67, 0xa9, 0x68, 0xc2,
|
0x57, 0xdd, 0x3a, 0x7d, 0x8f, 0xa7, 0xde, 0x4d, 0xbb, 0xb4, 0xf0, 0x33, 0xb4, 0x10, 0x71, 0xca,
|
||||||
0xc0, 0xff, 0xb4, 0xd0, 0x3b, 0x23, 0xc5, 0xeb, 0xe7, 0x51, 0xed, 0x89, 0x68, 0x68, 0x1b, 0x6d,
|
0x3b, 0x62, 0xe6, 0x05, 0xea, 0x9d, 0x73, 0xa1, 0x4a, 0xcd, 0xf4, 0xd2, 0x4a, 0xce, 0x44, 0x21,
|
||||||
0xa7, 0x6f, 0xbe, 0xde, 0x13, 0x3b, 0x63, 0xf4, 0x64, 0xac, 0x17, 0x7e, 0x8e, 0x0a, 0x7e, 0xd8,
|
0xd6, 0x7f, 0xd1, 0xd0, 0xfa, 0xb8, 0xca, 0x05, 0x14, 0xfb, 0xe3, 0xd1, 0x62, 0xdf, 0x38, 0x4f,
|
||||||
0xf6, 0x43, 0x48, 0x64, 0xbb, 0xe9, 0xb8, 0xc7, 0x5e, 0xe6, 0x61, 0x64, 0x3d, 0xe6, 0xd5, 0xb8,
|
0x44, 0x53, 0x0a, 0xfe, 0x9b, 0x86, 0xfe, 0x33, 0x11, 0xbc, 0xbc, 0x1e, 0xc5, 0x9e, 0x08, 0xc6,
|
||||||
0x57, 0x29, 0xd4, 0x87, 0x50, 0xc8, 0x08, 0x6e, 0xf5, 0x8f, 0x31, 0xe3, 0xd1, 0x6f, 0xe1, 0x35,
|
0xb6, 0xd1, 0x5e, 0x7a, 0xe7, 0xcb, 0x3d, 0xb1, 0x9f, 0xc3, 0x27, 0xb9, 0x5a, 0xf8, 0x05, 0x2a,
|
||||||
0xb4, 0x90, 0x7c, 0xcf, 0x01, 0x37, 0x65, 0xf4, 0xdb, 0xbd, 0x61, 0xe4, 0xa4, 0x6f, 0xa1, 0x19,
|
0x39, 0xbe, 0xeb, 0xf8, 0x90, 0xd0, 0x0e, 0xd2, 0x72, 0xe7, 0x0e, 0xf3, 0x38, 0xb2, 0x2c, 0xf3,
|
||||||
0xa4, 0x5b, 0x61, 0x12, 0x3d, 0x1b, 0x83, 0xb4, 0x67, 0x86, 0x41, 0xfa, 0x4c, 0x0c, 0xa2, 0xca,
|
0x7a, 0xdc, 0xaf, 0x95, 0x1a, 0x63, 0x28, 0x64, 0x02, 0xb7, 0xfe, 0x6b, 0x4e, 0x79, 0xe4, 0x5d,
|
||||||
0x44, 0x7d, 0x00, 0xe9, 0x86, 0xe6, 0x06, 0x33, 0xd9, 0x36, 0x72, 0xd2, 0xb7, 0xa8, 0xfe, 0x9b,
|
0x78, 0x03, 0x2d, 0x25, 0x8f, 0x46, 0x08, 0x55, 0x18, 0xc3, 0x74, 0x6f, 0x29, 0x3a, 0x19, 0x4a,
|
||||||
0x1b, 0x33, 0x25, 0x4d, 0xc5, 0x4c, 0x49, 0xc7, 0x9f, 0xb1, 0xc3, 0x25, 0x79, 0xfd, 0x92, 0x3c,
|
0xc8, 0x0e, 0x92, 0xa9, 0x50, 0x8e, 0x9e, 0xaf, 0x83, 0xa4, 0x66, 0xa6, 0x83, 0xe4, 0x99, 0x28,
|
||||||
0xfc, 0x83, 0x85, 0x30, 0xed, 0x43, 0x34, 0x8e, 0xa9, 0x9a, 0xf0, 0xe9, 0xc1, 0xd9, 0x6f, 0x88,
|
0x44, 0xe1, 0x89, 0x78, 0x00, 0xc9, 0x84, 0x16, 0x46, 0x3d, 0xd9, 0x53, 0x74, 0x32, 0x94, 0xa8,
|
||||||
0xbd, 0x31, 0x02, 0x96, 0xbc, 0x93, 0x25, 0x93, 0x04, 0x1e, 0x35, 0x20, 0x63, 0x32, 0xc0, 0x3e,
|
0xff, 0x5d, 0xc8, 0xa9, 0x92, 0x6c, 0xc5, 0x4c, 0x48, 0x83, 0xb7, 0xf2, 0x78, 0x48, 0xf6, 0x30,
|
||||||
0xca, 0x27, 0xd2, 0x2d, 0xce, 0x19, 0x37, 0x57, 0xf6, 0xf2, 0xc9, 0x09, 0x69, 0x73, 0xa7, 0xac,
|
0x24, 0x1b, 0x7f, 0xab, 0x21, 0x4c, 0x87, 0x10, 0xcd, 0x41, 0xab, 0x26, 0xfd, 0xf4, 0xe8, 0xfc,
|
||||||
0x3f, 0xe4, 0x52, 0xff, 0xa3, 0x5e, 0x25, 0x9f, 0xd1, 0x93, 0x2c, 0xb6, 0x0a, 0xe5, 0x41, 0x1a,
|
0x13, 0xa2, 0x6f, 0x4d, 0x80, 0x25, 0xf7, 0x64, 0x45, 0x39, 0x81, 0x27, 0x05, 0x48, 0x8e, 0x07,
|
||||||
0x6a, 0xe6, 0x7f, 0x84, 0xba, 0x0f, 0x93, 0x43, 0x65, 0xb0, 0x4b, 0x5b, 0xe8, 0xdd, 0x09, 0x0d,
|
0xd8, 0x41, 0xc5, 0x84, 0xba, 0x13, 0x86, 0x2c, 0x54, 0x23, 0x7b, 0xf5, 0x74, 0x87, 0xa4, 0xb8,
|
||||||
0x3a, 0xd3, 0xbb, 0xf2, 0x8d, 0x85, 0xb2, 0x31, 0xf0, 0x23, 0x34, 0xa3, 0xfe, 0x6a, 0x9a, 0x0d,
|
0x59, 0x95, 0x0f, 0xb9, 0x54, 0xff, 0xa4, 0x5f, 0x2b, 0x66, 0xf8, 0x24, 0x8b, 0x2d, 0x4c, 0xd9,
|
||||||
0x73, 0xf5, 0x74, 0x1b, 0x66, 0xcf, 0x0f, 0x20, 0x5d, 0x94, 0xea, 0x44, 0x34, 0x0a, 0xbe, 0x82,
|
0x90, 0x9a, 0x9a, 0xfb, 0x17, 0xa6, 0x1e, 0xc2, 0x74, 0x53, 0x19, 0xec, 0xca, 0x0e, 0xfa, 0xef,
|
||||||
0xe6, 0x03, 0x10, 0x82, 0xb6, 0x4c, 0xe4, 0xf4, 0xab, 0xaf, 0x91, 0x88, 0xc9, 0xb1, 0xbe, 0x7a,
|
0x94, 0x04, 0x9d, 0xeb, 0x5e, 0xf9, 0x4a, 0x43, 0x59, 0x1b, 0x78, 0x17, 0xcd, 0x89, 0xff, 0x59,
|
||||||
0x07, 0x5d, 0x1a, 0xf3, 0x1d, 0x8d, 0x2b, 0x68, 0xd6, 0xd5, 0xff, 0x85, 0x54, 0x42, 0xb3, 0xce,
|
0xb5, 0x61, 0xae, 0x9f, 0x6d, 0xc3, 0x1c, 0x3a, 0x1e, 0xa4, 0x8b, 0x52, 0x9c, 0x88, 0x44, 0xc1,
|
||||||
0xa2, 0xda, 0x32, 0x9b, 0xfa, 0x2f, 0x50, 0x22, 0x77, 0xae, 0xbf, 0x7c, 0x53, 0x9e, 0x7a, 0xf5,
|
0xd7, 0xd0, 0xa2, 0x07, 0x51, 0x44, 0xdb, 0xca, 0x72, 0xfa, 0xea, 0x6b, 0x26, 0x64, 0x32, 0xe0,
|
||||||
0xa6, 0x3c, 0xf5, 0xfa, 0x4d, 0x79, 0xea, 0xeb, 0xb8, 0x6c, 0xbd, 0x8c, 0xcb, 0xd6, 0xab, 0xb8,
|
0xd7, 0xef, 0xa1, 0x2b, 0x39, 0xef, 0x68, 0x5c, 0x43, 0xf3, 0x96, 0xfc, 0xe1, 0x12, 0x0e, 0xcd,
|
||||||
0x6c, 0xbd, 0x8e, 0xcb, 0xd6, 0x5f, 0x71, 0xd9, 0xfa, 0xee, 0xef, 0xf2, 0xd4, 0xd3, 0x79, 0xd3,
|
0x9b, 0xcb, 0x62, 0xcb, 0x6c, 0xcb, 0xff, 0xac, 0x84, 0x6e, 0xde, 0x7c, 0xf5, 0xb6, 0x3a, 0xf3,
|
||||||
0xef, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0xce, 0x65, 0xbb, 0xc7, 0x7f, 0x10, 0x00, 0x00,
|
0xfa, 0x6d, 0x75, 0xe6, 0xcd, 0xdb, 0xea, 0xcc, 0x97, 0x71, 0x55, 0x7b, 0x15, 0x57, 0xb5, 0xd7,
|
||||||
|
0x71, 0x55, 0x7b, 0x13, 0x57, 0xb5, 0xdf, 0xe3, 0xaa, 0xf6, 0xf5, 0x1f, 0xd5, 0x99, 0x67, 0x8b,
|
||||||
|
0x2a, 0xdf, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x72, 0xff, 0xde, 0x2e, 0xe4, 0x10, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *CSIDriver) Marshal() (dAtA []byte, err error) {
|
func (m *CSIDriver) Marshal() (dAtA []byte, err error) {
|
||||||
@ -715,6 +717,15 @@ func (m *CSIDriverSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
|||||||
_ = i
|
_ = i
|
||||||
var l int
|
var l int
|
||||||
_ = l
|
_ = l
|
||||||
|
if len(m.VolumeLifecycleModes) > 0 {
|
||||||
|
for iNdEx := len(m.VolumeLifecycleModes) - 1; iNdEx >= 0; iNdEx-- {
|
||||||
|
i -= len(m.VolumeLifecycleModes[iNdEx])
|
||||||
|
copy(dAtA[i:], m.VolumeLifecycleModes[iNdEx])
|
||||||
|
i = encodeVarintGenerated(dAtA, i, uint64(len(m.VolumeLifecycleModes[iNdEx])))
|
||||||
|
i--
|
||||||
|
dAtA[i] = 0x1a
|
||||||
|
}
|
||||||
|
}
|
||||||
if m.PodInfoOnMount != nil {
|
if m.PodInfoOnMount != nil {
|
||||||
i--
|
i--
|
||||||
if *m.PodInfoOnMount {
|
if *m.PodInfoOnMount {
|
||||||
@ -1458,6 +1469,12 @@ func (m *CSIDriverSpec) Size() (n int) {
|
|||||||
if m.PodInfoOnMount != nil {
|
if m.PodInfoOnMount != nil {
|
||||||
n += 2
|
n += 2
|
||||||
}
|
}
|
||||||
|
if len(m.VolumeLifecycleModes) > 0 {
|
||||||
|
for _, s := range m.VolumeLifecycleModes {
|
||||||
|
l = len(s)
|
||||||
|
n += 1 + l + sovGenerated(uint64(l))
|
||||||
|
}
|
||||||
|
}
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1745,6 +1762,7 @@ func (this *CSIDriverSpec) String() string {
|
|||||||
s := strings.Join([]string{`&CSIDriverSpec{`,
|
s := strings.Join([]string{`&CSIDriverSpec{`,
|
||||||
`AttachRequired:` + valueToStringGenerated(this.AttachRequired) + `,`,
|
`AttachRequired:` + valueToStringGenerated(this.AttachRequired) + `,`,
|
||||||
`PodInfoOnMount:` + valueToStringGenerated(this.PodInfoOnMount) + `,`,
|
`PodInfoOnMount:` + valueToStringGenerated(this.PodInfoOnMount) + `,`,
|
||||||
|
`VolumeLifecycleModes:` + fmt.Sprintf("%v", this.VolumeLifecycleModes) + `,`,
|
||||||
`}`,
|
`}`,
|
||||||
}, "")
|
}, "")
|
||||||
return s
|
return s
|
||||||
@ -2265,6 +2283,38 @@ func (m *CSIDriverSpec) Unmarshal(dAtA []byte) error {
|
|||||||
}
|
}
|
||||||
b := bool(v != 0)
|
b := bool(v != 0)
|
||||||
m.PodInfoOnMount = &b
|
m.PodInfoOnMount = &b
|
||||||
|
case 3:
|
||||||
|
if wireType != 2 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field VolumeLifecycleModes", wireType)
|
||||||
|
}
|
||||||
|
var stringLen uint64
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowGenerated
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
stringLen |= uint64(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
intStringLen := int(stringLen)
|
||||||
|
if intStringLen < 0 {
|
||||||
|
return ErrInvalidLengthGenerated
|
||||||
|
}
|
||||||
|
postIndex := iNdEx + intStringLen
|
||||||
|
if postIndex < 0 {
|
||||||
|
return ErrInvalidLengthGenerated
|
||||||
|
}
|
||||||
|
if postIndex > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
m.VolumeLifecycleModes = append(m.VolumeLifecycleModes, VolumeLifecycleMode(dAtA[iNdEx:postIndex]))
|
||||||
|
iNdEx = postIndex
|
||||||
default:
|
default:
|
||||||
iNdEx = preIndex
|
iNdEx = preIndex
|
||||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||||
|
@ -93,8 +93,32 @@ message CSIDriverSpec {
|
|||||||
// "csi.storage.k8s.io/pod.name": pod.Name
|
// "csi.storage.k8s.io/pod.name": pod.Name
|
||||||
// "csi.storage.k8s.io/pod.namespace": pod.Namespace
|
// "csi.storage.k8s.io/pod.namespace": pod.Namespace
|
||||||
// "csi.storage.k8s.io/pod.uid": string(pod.UID)
|
// "csi.storage.k8s.io/pod.uid": string(pod.UID)
|
||||||
|
// "csi.storage.k8s.io/ephemeral": "true" iff the volume is an ephemeral inline volume
|
||||||
|
// defined by a CSIVolumeSource, otherwise "false"
|
||||||
|
//
|
||||||
|
// "csi.storage.k8s.io/ephemeral" is a new feature in Kubernetes 1.16. It is only
|
||||||
|
// required for drivers which support both the "Persistent" and "Ephemeral" VolumeLifecycleMode.
|
||||||
|
// Other drivers can leave pod info disabled and/or ignore this field.
|
||||||
|
// As Kubernetes 1.15 doesn't support this field, drivers can only support one mode when
|
||||||
|
// deployed on such a cluster and the deployment determines which mode that is, for example
|
||||||
|
// via a command line parameter of the driver.
|
||||||
// +optional
|
// +optional
|
||||||
optional bool podInfoOnMount = 2;
|
optional bool podInfoOnMount = 2;
|
||||||
|
|
||||||
|
// VolumeLifecycleModes defines what kind of volumes this CSI volume driver supports.
|
||||||
|
// The default if the list is empty is "Persistent", which is the usage
|
||||||
|
// defined by the CSI specification and implemented in Kubernetes via the usual
|
||||||
|
// PV/PVC mechanism.
|
||||||
|
// The other mode is "Ephemeral". In this mode, volumes are defined inline
|
||||||
|
// inside the pod spec with CSIVolumeSource and their lifecycle is tied to
|
||||||
|
// the lifecycle of that pod. A driver has to be aware of this
|
||||||
|
// because it is only going to get a NodePublishVolume call for such a volume.
|
||||||
|
// For more information about implementing this mode, see
|
||||||
|
// https://kubernetes-csi.github.io/docs/ephemeral-local-volumes.html
|
||||||
|
// A driver can support one or more of these modes and
|
||||||
|
// more modes may be added in the future.
|
||||||
|
// +optional
|
||||||
|
repeated string volumeLifecycleModes = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CSINode holds information about all CSI drivers installed on a node.
|
// CSINode holds information about all CSI drivers installed on a node.
|
||||||
|
@ -291,10 +291,59 @@ type CSIDriverSpec struct {
|
|||||||
// "csi.storage.k8s.io/pod.name": pod.Name
|
// "csi.storage.k8s.io/pod.name": pod.Name
|
||||||
// "csi.storage.k8s.io/pod.namespace": pod.Namespace
|
// "csi.storage.k8s.io/pod.namespace": pod.Namespace
|
||||||
// "csi.storage.k8s.io/pod.uid": string(pod.UID)
|
// "csi.storage.k8s.io/pod.uid": string(pod.UID)
|
||||||
|
// "csi.storage.k8s.io/ephemeral": "true" iff the volume is an ephemeral inline volume
|
||||||
|
// defined by a CSIVolumeSource, otherwise "false"
|
||||||
|
//
|
||||||
|
// "csi.storage.k8s.io/ephemeral" is a new feature in Kubernetes 1.16. It is only
|
||||||
|
// required for drivers which support both the "Persistent" and "Ephemeral" VolumeLifecycleMode.
|
||||||
|
// Other drivers can leave pod info disabled and/or ignore this field.
|
||||||
|
// As Kubernetes 1.15 doesn't support this field, drivers can only support one mode when
|
||||||
|
// deployed on such a cluster and the deployment determines which mode that is, for example
|
||||||
|
// via a command line parameter of the driver.
|
||||||
// +optional
|
// +optional
|
||||||
PodInfoOnMount *bool `json:"podInfoOnMount,omitempty" protobuf:"bytes,2,opt,name=podInfoOnMount"`
|
PodInfoOnMount *bool `json:"podInfoOnMount,omitempty" protobuf:"bytes,2,opt,name=podInfoOnMount"`
|
||||||
|
|
||||||
|
// VolumeLifecycleModes defines what kind of volumes this CSI volume driver supports.
|
||||||
|
// The default if the list is empty is "Persistent", which is the usage
|
||||||
|
// defined by the CSI specification and implemented in Kubernetes via the usual
|
||||||
|
// PV/PVC mechanism.
|
||||||
|
// The other mode is "Ephemeral". In this mode, volumes are defined inline
|
||||||
|
// inside the pod spec with CSIVolumeSource and their lifecycle is tied to
|
||||||
|
// the lifecycle of that pod. A driver has to be aware of this
|
||||||
|
// because it is only going to get a NodePublishVolume call for such a volume.
|
||||||
|
// For more information about implementing this mode, see
|
||||||
|
// https://kubernetes-csi.github.io/docs/ephemeral-local-volumes.html
|
||||||
|
// A driver can support one or more of these modes and
|
||||||
|
// more modes may be added in the future.
|
||||||
|
// +optional
|
||||||
|
VolumeLifecycleModes []VolumeLifecycleMode `json:"volumeLifecycleModes,omitempty" protobuf:"bytes,3,opt,name=volumeLifecycleModes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VolumeLifecycleMode is an enumeration of possible usage modes for a volume
|
||||||
|
// provided by a CSI driver. More modes may be added in the future.
|
||||||
|
type VolumeLifecycleMode string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// VolumeLifecyclePersistent explicitly confirms that the driver implements
|
||||||
|
// the full CSI spec. It is the default when CSIDriverSpec.VolumeLifecycleModes is not
|
||||||
|
// set. Such volumes are managed in Kubernetes via the persistent volume
|
||||||
|
// claim mechanism and have a lifecycle that is independent of the pods which
|
||||||
|
// use them.
|
||||||
|
VolumeLifecyclePersistent VolumeLifecycleMode = "Persistent"
|
||||||
|
|
||||||
|
// VolumeLifecycleEphemeral indicates that the driver can be used for
|
||||||
|
// ephemeral inline volumes. Such volumes are specified inside the pod
|
||||||
|
// spec with a CSIVolumeSource and, as far as Kubernetes is concerned, have
|
||||||
|
// a lifecycle that is tied to the lifecycle of the pod. For example, such
|
||||||
|
// a volume might contain data that gets created specifically for that pod,
|
||||||
|
// like secrets.
|
||||||
|
// But how the volume actually gets created and managed is entirely up to
|
||||||
|
// the driver. It might also use reference counting to share the same volume
|
||||||
|
// instance among different pods if the CSIVolumeSource of those pods is
|
||||||
|
// identical.
|
||||||
|
VolumeLifecycleEphemeral VolumeLifecycleMode = "Ephemeral"
|
||||||
|
)
|
||||||
|
|
||||||
// +genclient
|
// +genclient
|
||||||
// +genclient:nonNamespaced
|
// +genclient:nonNamespaced
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
@ -50,7 +50,8 @@ func (CSIDriverList) SwaggerDoc() map[string]string {
|
|||||||
var map_CSIDriverSpec = map[string]string{
|
var map_CSIDriverSpec = map[string]string{
|
||||||
"": "CSIDriverSpec is the specification of a CSIDriver.",
|
"": "CSIDriverSpec is the specification of a CSIDriver.",
|
||||||
"attachRequired": "attachRequired indicates this CSI volume driver requires an attach operation (because it implements the CSI ControllerPublishVolume() method), and that the Kubernetes attach detach controller should call the attach volume interface which checks the volumeattachment status and waits until the volume is attached before proceeding to mounting. The CSI external-attacher coordinates with CSI volume driver and updates the volumeattachment status when the attach operation is complete. If the CSIDriverRegistry feature gate is enabled and the value is specified to false, the attach operation will be skipped. Otherwise the attach operation will be called.",
|
"attachRequired": "attachRequired indicates this CSI volume driver requires an attach operation (because it implements the CSI ControllerPublishVolume() method), and that the Kubernetes attach detach controller should call the attach volume interface which checks the volumeattachment status and waits until the volume is attached before proceeding to mounting. The CSI external-attacher coordinates with CSI volume driver and updates the volumeattachment status when the attach operation is complete. If the CSIDriverRegistry feature gate is enabled and the value is specified to false, the attach operation will be skipped. Otherwise the attach operation will be called.",
|
||||||
"podInfoOnMount": "If set to true, podInfoOnMount indicates this CSI volume driver requires additional pod information (like podName, podUID, etc.) during mount operations. If set to false, pod information will not be passed on mount. Default is false. The CSI driver specifies podInfoOnMount as part of driver deployment. If true, Kubelet will pass pod information as VolumeContext in the CSI NodePublishVolume() calls. The CSI driver is responsible for parsing and validating the information passed in as VolumeContext. The following VolumeConext will be passed if podInfoOnMount is set to true. This list might grow, but the prefix will be used. \"csi.storage.k8s.io/pod.name\": pod.Name \"csi.storage.k8s.io/pod.namespace\": pod.Namespace \"csi.storage.k8s.io/pod.uid\": string(pod.UID)",
|
"podInfoOnMount": "If set to true, podInfoOnMount indicates this CSI volume driver requires additional pod information (like podName, podUID, etc.) during mount operations. If set to false, pod information will not be passed on mount. Default is false. The CSI driver specifies podInfoOnMount as part of driver deployment. If true, Kubelet will pass pod information as VolumeContext in the CSI NodePublishVolume() calls. The CSI driver is responsible for parsing and validating the information passed in as VolumeContext. The following VolumeConext will be passed if podInfoOnMount is set to true. This list might grow, but the prefix will be used. \"csi.storage.k8s.io/pod.name\": pod.Name \"csi.storage.k8s.io/pod.namespace\": pod.Namespace \"csi.storage.k8s.io/pod.uid\": string(pod.UID) \"csi.storage.k8s.io/ephemeral\": \"true\" iff the volume is an ephemeral inline volume\n defined by a CSIVolumeSource, otherwise \"false\"\n\n\"csi.storage.k8s.io/ephemeral\" is a new feature in Kubernetes 1.16. It is only required for drivers which support both the \"Persistent\" and \"Ephemeral\" VolumeLifecycleMode. Other drivers can leave pod info disabled and/or ignore this field. As Kubernetes 1.15 doesn't support this field, drivers can only support one mode when deployed on such a cluster and the deployment determines which mode that is, for example via a command line parameter of the driver.",
|
||||||
|
"volumeLifecycleModes": "VolumeLifecycleModes defines what kind of volumes this CSI volume driver supports. The default if the list is empty is \"Persistent\", which is the usage defined by the CSI specification and implemented in Kubernetes via the usual PV/PVC mechanism. The other mode is \"Ephemeral\". In this mode, volumes are defined inline inside the pod spec with CSIVolumeSource and their lifecycle is tied to the lifecycle of that pod. A driver has to be aware of this because it is only going to get a NodePublishVolume call for such a volume. For more information about implementing this mode, see https://kubernetes-csi.github.io/docs/ephemeral-local-volumes.html A driver can support one or more of these modes and more modes may be added in the future.",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (CSIDriverSpec) SwaggerDoc() map[string]string {
|
func (CSIDriverSpec) SwaggerDoc() map[string]string {
|
||||||
|
@ -98,6 +98,11 @@ func (in *CSIDriverSpec) DeepCopyInto(out *CSIDriverSpec) {
|
|||||||
*out = new(bool)
|
*out = new(bool)
|
||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
|
if in.VolumeLifecycleModes != nil {
|
||||||
|
in, out := &in.VolumeLifecycleModes, &out.VolumeLifecycleModes
|
||||||
|
*out = make([]VolumeLifecycleMode, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,9 @@
|
|||||||
},
|
},
|
||||||
"spec": {
|
"spec": {
|
||||||
"attachRequired": false,
|
"attachRequired": false,
|
||||||
"podInfoOnMount": false
|
"podInfoOnMount": false,
|
||||||
|
"volumeLifecycleModes": [
|
||||||
|
"r鯹)晿\u003co,c鮽ort昍řČ扷5ƗǸ"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
Binary file not shown.
@ -31,3 +31,5 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
attachRequired: false
|
attachRequired: false
|
||||||
podInfoOnMount: false
|
podInfoOnMount: false
|
||||||
|
volumeLifecycleModes:
|
||||||
|
- r鯹)晿<o,c鮽ort昍řČ扷5ƗǸ
|
||||||
|
@ -13,6 +13,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
|
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/api/storage/v1:go_default_library",
|
"//staging/src/k8s.io/api/storage/v1:go_default_library",
|
||||||
|
"//staging/src/k8s.io/api/storage/v1beta1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
|
||||||
|
@ -43,6 +43,7 @@ import (
|
|||||||
"github.com/onsi/ginkgo"
|
"github.com/onsi/ginkgo"
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
storagev1 "k8s.io/api/storage/v1"
|
storagev1 "k8s.io/api/storage/v1"
|
||||||
|
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/kubernetes/test/e2e/framework"
|
"k8s.io/kubernetes/test/e2e/framework"
|
||||||
@ -196,7 +197,6 @@ var _ testsuites.DynamicPVTestDriver = &mockCSIDriver{}
|
|||||||
// InitMockCSIDriver returns a mockCSIDriver that implements TestDriver interface
|
// InitMockCSIDriver returns a mockCSIDriver that implements TestDriver interface
|
||||||
func InitMockCSIDriver(driverOpts CSIMockDriverOpts) testsuites.TestDriver {
|
func InitMockCSIDriver(driverOpts CSIMockDriverOpts) testsuites.TestDriver {
|
||||||
driverManifests := []string{
|
driverManifests := []string{
|
||||||
"test/e2e/testing-manifests/storage-csi/cluster-driver-registrar/rbac.yaml",
|
|
||||||
"test/e2e/testing-manifests/storage-csi/driver-registrar/rbac.yaml",
|
"test/e2e/testing-manifests/storage-csi/driver-registrar/rbac.yaml",
|
||||||
"test/e2e/testing-manifests/storage-csi/external-attacher/rbac.yaml",
|
"test/e2e/testing-manifests/storage-csi/external-attacher/rbac.yaml",
|
||||||
"test/e2e/testing-manifests/storage-csi/external-provisioner/rbac.yaml",
|
"test/e2e/testing-manifests/storage-csi/external-provisioner/rbac.yaml",
|
||||||
@ -207,7 +207,7 @@ func InitMockCSIDriver(driverOpts CSIMockDriverOpts) testsuites.TestDriver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if driverOpts.RegisterDriver {
|
if driverOpts.RegisterDriver {
|
||||||
driverManifests = append(driverManifests, "test/e2e/testing-manifests/storage-csi/mock/csi-mock-cluster-driver-registrar.yaml")
|
driverManifests = append(driverManifests, "test/e2e/testing-manifests/storage-csi/mock/csi-mock-driverinfo.yaml")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !driverOpts.DisableAttach {
|
if !driverOpts.DisableAttach {
|
||||||
@ -294,9 +294,13 @@ func (m *mockCSIDriver) PrepareTest(f *framework.Framework) (*testsuites.PerTest
|
|||||||
DriverContainerName: "mock",
|
DriverContainerName: "mock",
|
||||||
DriverContainerArguments: containerArgs,
|
DriverContainerArguments: containerArgs,
|
||||||
ProvisionerContainerName: "csi-provisioner",
|
ProvisionerContainerName: "csi-provisioner",
|
||||||
ClusterRegistrarContainerName: "csi-cluster-driver-registrar",
|
|
||||||
NodeName: config.ClientNodeName,
|
NodeName: config.ClientNodeName,
|
||||||
PodInfo: m.podInfo,
|
PodInfo: m.podInfo,
|
||||||
|
CanAttach: &m.attachable,
|
||||||
|
VolumeLifecycleModes: []storagev1beta1.VolumeLifecycleMode{
|
||||||
|
storagev1beta1.VolumeLifecyclePersistent,
|
||||||
|
storagev1beta1.VolumeLifecycleEphemeral,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
cleanup, err := f.CreateFromManifests(func(item interface{}) error {
|
cleanup, err := f.CreateFromManifests(func(item interface{}) error {
|
||||||
return utils.PatchCSIDeployment(f, o, item)
|
return utils.PatchCSIDeployment(f, o, item)
|
||||||
|
@ -114,7 +114,9 @@ type EphemeralTestDriver interface {
|
|||||||
|
|
||||||
// GetCSIDriverName returns the name that was used when registering with
|
// GetCSIDriverName returns the name that was used when registering with
|
||||||
// kubelet. Depending on how the driver was deployed, this can be different
|
// kubelet. Depending on how the driver was deployed, this can be different
|
||||||
// from DriverInfo.Name.
|
// from DriverInfo.Name. Starting with Kubernetes 1.16, there must also
|
||||||
|
// be a CSIDriver object under the same name with a "mode" field that enables
|
||||||
|
// usage of the driver for ephemeral inline volumes.
|
||||||
GetCSIDriverName(config *PerTestConfig) string
|
GetCSIDriverName(config *PerTestConfig) string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
|
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/api/storage/v1:go_default_library",
|
"//staging/src/k8s.io/api/storage/v1:go_default_library",
|
||||||
|
"//staging/src/k8s.io/api/storage/v1beta1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
|
||||||
|
@ -18,12 +18,12 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
storagev1 "k8s.io/api/storage/v1"
|
storagev1 "k8s.io/api/storage/v1"
|
||||||
|
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
||||||
"k8s.io/kubernetes/test/e2e/framework"
|
"k8s.io/kubernetes/test/e2e/framework"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -94,10 +94,6 @@ func PatchCSIDeployment(f *framework.Framework, o PatchCSIOptions, object interf
|
|||||||
// Driver name is expected to be the same
|
// Driver name is expected to be the same
|
||||||
// as the snapshotter here.
|
// as the snapshotter here.
|
||||||
container.Args = append(container.Args, "--snapshotter="+o.NewDriverName)
|
container.Args = append(container.Args, "--snapshotter="+o.NewDriverName)
|
||||||
case o.ClusterRegistrarContainerName:
|
|
||||||
if o.PodInfo != nil {
|
|
||||||
container.Args = append(container.Args, "--pod-info-mount="+strconv.FormatBool(*o.PodInfo))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,6 +121,17 @@ func PatchCSIDeployment(f *framework.Framework, o PatchCSIOptions, object interf
|
|||||||
// as the provisioner name here.
|
// as the provisioner name here.
|
||||||
object.Provisioner = o.NewDriverName
|
object.Provisioner = o.NewDriverName
|
||||||
}
|
}
|
||||||
|
case *storagev1beta1.CSIDriver:
|
||||||
|
if o.NewDriverName != "" {
|
||||||
|
object.Name = o.NewDriverName
|
||||||
|
}
|
||||||
|
if o.PodInfo != nil {
|
||||||
|
object.Spec.PodInfoOnMount = o.PodInfo
|
||||||
|
}
|
||||||
|
if o.CanAttach != nil {
|
||||||
|
object.Spec.AttachRequired = o.CanAttach
|
||||||
|
}
|
||||||
|
object.Spec.VolumeLifecycleModes = o.VolumeLifecycleModes
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -154,12 +161,18 @@ type PatchCSIOptions struct {
|
|||||||
// If non-empty, --snapshotter with new name will be appended
|
// If non-empty, --snapshotter with new name will be appended
|
||||||
// to the argument list.
|
// to the argument list.
|
||||||
SnapshotterContainerName string
|
SnapshotterContainerName string
|
||||||
// The name of the container which has the cluster-driver-registrar
|
|
||||||
// binary.
|
|
||||||
ClusterRegistrarContainerName string
|
|
||||||
// If non-empty, all pods are forced to run on this node.
|
// If non-empty, all pods are forced to run on this node.
|
||||||
NodeName string
|
NodeName string
|
||||||
// If not nil, the argument to pass to the cluster-driver-registrar's
|
// If not nil, the value to use for the CSIDriver.Spec.PodInfo
|
||||||
// pod-info-mount argument.
|
// field *if* the driver deploys a CSIDriver object. Ignored
|
||||||
|
// otherwise.
|
||||||
PodInfo *bool
|
PodInfo *bool
|
||||||
|
// If not nil, the value to use for the CSIDriver.Spec.CanAttach
|
||||||
|
// field *if* the driver deploys a CSIDriver object. Ignored
|
||||||
|
// otherwise.
|
||||||
|
CanAttach *bool
|
||||||
|
// The value to use for the CSIDriver.Spec.VolumeLifecycleModes
|
||||||
|
// field *if* the driver deploys a CSIDriver object. Ignored
|
||||||
|
// otherwise.
|
||||||
|
VolumeLifecycleModes []storagev1beta1.VolumeLifecycleMode
|
||||||
}
|
}
|
||||||
|
@ -1 +0,0 @@
|
|||||||
The original file is (or will be) https://github.com/kubernetes-csi/cluster-driver-registrar/blob/master/deploy/kubernetes/rbac.yaml
|
|
@ -1,38 +0,0 @@
|
|||||||
# This YAML file contains all RBAC objects that are necessary to run
|
|
||||||
# cluster-driver-registrar.
|
|
||||||
#
|
|
||||||
# In production, each CSI driver deployment has to be customized:
|
|
||||||
# - to avoid conflicts, use non-default namespace and different names
|
|
||||||
# for non-namespaced entities like the ClusterRole
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: csi-cluster-driver-registrar
|
|
||||||
# replace with non-default namespace name
|
|
||||||
namespace: default
|
|
||||||
|
|
||||||
---
|
|
||||||
kind: ClusterRole
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: cluster-driver-registrar-runner
|
|
||||||
rules:
|
|
||||||
- apiGroups: ["storage.k8s.io"]
|
|
||||||
resources: ["csidrivers"]
|
|
||||||
verbs: ["create", "delete"]
|
|
||||||
|
|
||||||
---
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: csi-cluster-driver-registrar-role
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: csi-cluster-driver-registrar
|
|
||||||
# replace with non-default namespace name
|
|
||||||
namespace: default
|
|
||||||
roleRef:
|
|
||||||
kind: ClusterRole
|
|
||||||
name: cluster-driver-registrar-runner
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
@ -1,36 +0,0 @@
|
|||||||
kind: StatefulSet
|
|
||||||
apiVersion: apps/v1
|
|
||||||
metadata:
|
|
||||||
name: csi-mockplugin-cluster-driver-registrar
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: csi-mockplugin-cluster-driver-registrar
|
|
||||||
replicas: 1
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: csi-mockplugin-cluster-driver-registrar
|
|
||||||
spec:
|
|
||||||
serviceAccountName: csi-mock
|
|
||||||
containers:
|
|
||||||
- name: csi-cluster-driver-registrar
|
|
||||||
# TODO: replace with official image
|
|
||||||
image: quay.io/k8scsi/csi-cluster-driver-registrar:tmp-test-1.14
|
|
||||||
args:
|
|
||||||
- --v=5
|
|
||||||
- --csi-address=$(ADDRESS)
|
|
||||||
env:
|
|
||||||
- name: ADDRESS
|
|
||||||
value: /csi/csi.sock
|
|
||||||
imagePullPolicy: Always
|
|
||||||
securityContext:
|
|
||||||
privileged: true
|
|
||||||
volumeMounts:
|
|
||||||
- mountPath: /csi
|
|
||||||
name: socket-dir
|
|
||||||
volumes:
|
|
||||||
- hostPath:
|
|
||||||
path: /var/lib/kubelet/plugins/csi-mock
|
|
||||||
type: DirectoryOrCreate
|
|
||||||
name: socket-dir
|
|
@ -18,7 +18,6 @@ spec:
|
|||||||
# TODO: replace with official 1.4.0 release when ready
|
# TODO: replace with official 1.4.0 release when ready
|
||||||
image: quay.io/k8scsi/csi-provisioner:v1.4.0-rc1
|
image: quay.io/k8scsi/csi-provisioner:v1.4.0-rc1
|
||||||
args:
|
args:
|
||||||
- "--provisioner=csi-hostpath"
|
|
||||||
- "--csi-address=$(ADDRESS)"
|
- "--csi-address=$(ADDRESS)"
|
||||||
- "--connection-timeout=15s"
|
- "--connection-timeout=15s"
|
||||||
env:
|
env:
|
||||||
@ -51,6 +50,7 @@ spec:
|
|||||||
- name: mock
|
- name: mock
|
||||||
image: quay.io/k8scsi/mock-driver:v2.1.0
|
image: quay.io/k8scsi/mock-driver:v2.1.0
|
||||||
args:
|
args:
|
||||||
|
- "--name=mock.storage.k8s.io"
|
||||||
- "--permissive-target-path" # because of https://github.com/kubernetes/kubernetes/issues/75535
|
- "--permissive-target-path" # because of https://github.com/kubernetes/kubernetes/issues/75535
|
||||||
env:
|
env:
|
||||||
- name: CSI_ENDPOINT
|
- name: CSI_ENDPOINT
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: storage.k8s.io/v1beta1
|
||||||
|
kind: CSIDriver
|
||||||
|
metadata:
|
||||||
|
name: mock.storage.k8s.io
|
||||||
|
# Intentionally no spec. All values in the
|
||||||
|
# spec will be inserted dynamically by PatchCSIDeployment()
|
||||||
|
# in test/e2e/storage/utils/deployment.go.
|
Loading…
Reference in New Issue
Block a user