mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 05:27:21 +00:00
CSI - API change for CSI volume source type
This commit tracks source code update to support the CSI volume source type additionn.
This commit is contained in:
parent
6a3d3a42db
commit
af0c2bda94
@ -391,6 +391,9 @@ type PersistentVolumeSource struct {
|
|||||||
// More info: https://releases.k8s.io/HEAD/examples/volumes/storageos/README.md
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/storageos/README.md
|
||||||
// +optional
|
// +optional
|
||||||
StorageOS *StorageOSPersistentVolumeSource
|
StorageOS *StorageOSPersistentVolumeSource
|
||||||
|
// CSI (Container Storage Interface) represents storage that handled by an external CSI driver
|
||||||
|
// +optional
|
||||||
|
CSI *CSIPersistentVolumeSource
|
||||||
}
|
}
|
||||||
|
|
||||||
type PersistentVolumeClaimVolumeSource struct {
|
type PersistentVolumeClaimVolumeSource struct {
|
||||||
@ -1503,6 +1506,23 @@ type LocalVolumeSource struct {
|
|||||||
Path string
|
Path string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Represents storage that is managed by an external CSI volume driver
|
||||||
|
type CSIPersistentVolumeSource struct {
|
||||||
|
// Driver is the name of the driver to use for this volume.
|
||||||
|
// Required.
|
||||||
|
Driver string
|
||||||
|
|
||||||
|
// VolumeHandle is the unique volume name returned by the CSI volume
|
||||||
|
// plugin’s CreateVolume to refer to the volume on all subsequent calls.
|
||||||
|
// Required.
|
||||||
|
VolumeHandle string
|
||||||
|
|
||||||
|
// Optional: The value to pass to ControllerPublishVolumeRequest.
|
||||||
|
// Defaults to false (read/write).
|
||||||
|
// +optional
|
||||||
|
ReadOnly bool
|
||||||
|
}
|
||||||
|
|
||||||
// ContainerPort represents a network port in a single container
|
// ContainerPort represents a network port in a single container
|
||||||
type ContainerPort struct {
|
type ContainerPort struct {
|
||||||
// Optional: If specified, this must be an IANA_SVC_NAME Each named port
|
// Optional: If specified, this must be an IANA_SVC_NAME Each named port
|
||||||
|
@ -1318,6 +1318,24 @@ func validateStorageOSPersistentVolumeSource(storageos *core.StorageOSPersistent
|
|||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateCSIPersistentVolumeSource(csi *api.CSIPersistentVolumeSource, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
|
||||||
|
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) {
|
||||||
|
allErrs = append(allErrs, field.Forbidden(fldPath, "CSIPersistentVolume disabled by feature-gate"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(csi.Driver) == 0 {
|
||||||
|
allErrs = append(allErrs, field.Required(fldPath.Child("driver"), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(csi.VolumeHandle) == 0 {
|
||||||
|
allErrs = append(allErrs, field.Required(fldPath.Child("volumeHandle"), ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
// ValidatePersistentVolumeName checks that a name is appropriate for a
|
// ValidatePersistentVolumeName checks that a name is appropriate for a
|
||||||
// PersistentVolumeName object.
|
// PersistentVolumeName object.
|
||||||
var ValidatePersistentVolumeName = NameIsDNSSubdomain
|
var ValidatePersistentVolumeName = NameIsDNSSubdomain
|
||||||
@ -1541,6 +1559,15 @@ func ValidatePersistentVolume(pv *core.PersistentVolume) field.ErrorList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pv.Spec.CSI != nil {
|
||||||
|
if numVolumes > 0 {
|
||||||
|
allErrs = append(allErrs, field.Forbidden(specPath.Child("csi"), "may not specify more than 1 volume type"))
|
||||||
|
} else {
|
||||||
|
numVolumes++
|
||||||
|
allErrs = append(allErrs, validateCSIPersistentVolumeSource(pv.Spec.CSI, specPath.Child("csi"))...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if numVolumes == 0 {
|
if numVolumes == 0 {
|
||||||
allErrs = append(allErrs, field.Required(specPath, "must specify a volume type"))
|
allErrs = append(allErrs, field.Required(specPath, "must specify a volume type"))
|
||||||
}
|
}
|
||||||
|
@ -1353,6 +1353,64 @@ func TestValidateGlusterfs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateCSIVolumeSource(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
csi *api.CSIPersistentVolumeSource
|
||||||
|
errtype field.ErrorType
|
||||||
|
errfield string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "all required fields ok",
|
||||||
|
csi: &api.CSIPersistentVolumeSource{Driver: "test-driver", VolumeHandle: "test-123", ReadOnly: true},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with default values ok",
|
||||||
|
csi: &api.CSIPersistentVolumeSource{Driver: "test-driver", VolumeHandle: "test-123"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "missing driver name",
|
||||||
|
csi: &api.CSIPersistentVolumeSource{VolumeHandle: "test-123"},
|
||||||
|
errtype: field.ErrorTypeRequired,
|
||||||
|
errfield: "driver",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "missing volume handle",
|
||||||
|
csi: &api.CSIPersistentVolumeSource{Driver: "my-driver"},
|
||||||
|
errtype: field.ErrorTypeRequired,
|
||||||
|
errfield: "volumeHandle",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := utilfeature.DefaultFeatureGate.Set("CSIPersistentVolume=true")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to enable feature gate for CSIPersistentVolumes: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tc := range testCases {
|
||||||
|
errs := validateCSIPersistentVolumeSource(tc.csi, field.NewPath("field"))
|
||||||
|
|
||||||
|
if len(errs) > 0 && tc.errtype == "" {
|
||||||
|
t.Errorf("[%d: %q] unexpected error(s): %v", i, tc.name, errs)
|
||||||
|
} else if len(errs) == 0 && tc.errtype != "" {
|
||||||
|
t.Errorf("[%d: %q] expected error type %v", i, tc.name, tc.errtype)
|
||||||
|
} else if len(errs) >= 1 {
|
||||||
|
if errs[0].Type != tc.errtype {
|
||||||
|
t.Errorf("[%d: %q] expected error type %v, got %v", i, tc.name, tc.errtype, errs[0].Type)
|
||||||
|
} else if !strings.HasSuffix(errs[0].Field, "."+tc.errfield) {
|
||||||
|
t.Errorf("[%d: %q] expected error on field %q, got %q", i, tc.name, tc.errfield, errs[0].Field)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = utilfeature.DefaultFeatureGate.Set("CSIPersistentVolume=false")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to disable feature gate for CSIPersistentVolumes: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// helper
|
// helper
|
||||||
func newInt32(val int) *int32 {
|
func newInt32(val int) *int32 {
|
||||||
p := new(int32)
|
p := new(int32)
|
||||||
|
@ -919,6 +919,7 @@ var (
|
|||||||
Projected FSType = "projected"
|
Projected FSType = "projected"
|
||||||
PortworxVolume FSType = "portworxVolume"
|
PortworxVolume FSType = "portworxVolume"
|
||||||
ScaleIO FSType = "scaleIO"
|
ScaleIO FSType = "scaleIO"
|
||||||
|
CSI FSType = "csi"
|
||||||
All FSType = "*"
|
All FSType = "*"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -181,6 +181,12 @@ const (
|
|||||||
//
|
//
|
||||||
// Extend the default scheduler to be aware of PV topology and handle PV binding
|
// Extend the default scheduler to be aware of PV topology and handle PV binding
|
||||||
VolumeScheduling utilfeature.Feature = "VolumeScheduling"
|
VolumeScheduling utilfeature.Feature = "VolumeScheduling"
|
||||||
|
|
||||||
|
// owner: @vladimirvivien
|
||||||
|
// alpha: v1.9
|
||||||
|
//
|
||||||
|
// Enable mount/attachment of Container Storage Interface (CSI) backed PVs
|
||||||
|
CSIPersistentVolume utilfeature.Feature = "CSIPersistentVolume"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -215,6 +221,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS
|
|||||||
ServiceNodeExclusion: {Default: false, PreRelease: utilfeature.Alpha},
|
ServiceNodeExclusion: {Default: false, PreRelease: utilfeature.Alpha},
|
||||||
MountContainers: {Default: false, PreRelease: utilfeature.Alpha},
|
MountContainers: {Default: false, PreRelease: utilfeature.Alpha},
|
||||||
VolumeScheduling: {Default: false, PreRelease: utilfeature.Alpha},
|
VolumeScheduling: {Default: false, PreRelease: utilfeature.Alpha},
|
||||||
|
CSIPersistentVolume: {Default: false, PreRelease: utilfeature.Alpha},
|
||||||
|
|
||||||
// inherited features from generic apiserver, relisted here to get a conflict if it is changed
|
// inherited features from generic apiserver, relisted here to get a conflict if it is changed
|
||||||
// unintentionally on either side:
|
// unintentionally on either side:
|
||||||
|
@ -1073,6 +1073,14 @@ func printFlockerVolumeSource(flocker *api.FlockerVolumeSource, w PrefixWriter)
|
|||||||
flocker.DatasetName, flocker.DatasetUUID)
|
flocker.DatasetName, flocker.DatasetUUID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printCSIPersistentVolumeSource(csi *api.CSIPersistentVolumeSource, w PrefixWriter) {
|
||||||
|
w.Write(LEVEL_2, "Type:\tCSI (a Container Storage Interface (CSI) volume source)\n"+
|
||||||
|
" Driver:\t%v\n"+
|
||||||
|
" VolumeHandle:\t%v\n",
|
||||||
|
" ReadOnly:\t%v\n",
|
||||||
|
csi.Driver, csi.VolumeHandle, csi.ReadOnly)
|
||||||
|
}
|
||||||
|
|
||||||
type PersistentVolumeDescriber struct {
|
type PersistentVolumeDescriber struct {
|
||||||
clientset.Interface
|
clientset.Interface
|
||||||
}
|
}
|
||||||
@ -1156,6 +1164,8 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) (
|
|||||||
printFlexVolumeSource(pv.Spec.FlexVolume, w)
|
printFlexVolumeSource(pv.Spec.FlexVolume, w)
|
||||||
case pv.Spec.Flocker != nil:
|
case pv.Spec.Flocker != nil:
|
||||||
printFlockerVolumeSource(pv.Spec.Flocker, w)
|
printFlockerVolumeSource(pv.Spec.Flocker, w)
|
||||||
|
case pv.Spec.CSI != nil:
|
||||||
|
printCSIPersistentVolumeSource(pv.Spec.CSI, w)
|
||||||
default:
|
default:
|
||||||
w.Write(LEVEL_1, "<unknown>\n")
|
w.Write(LEVEL_1, "<unknown>\n")
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,7 @@ func GetAllFSTypesAsSet() sets.String {
|
|||||||
string(extensions.Projected),
|
string(extensions.Projected),
|
||||||
string(extensions.PortworxVolume),
|
string(extensions.PortworxVolume),
|
||||||
string(extensions.ScaleIO),
|
string(extensions.ScaleIO),
|
||||||
|
string(extensions.CSI),
|
||||||
)
|
)
|
||||||
return fstypes
|
return fstypes
|
||||||
}
|
}
|
||||||
|
@ -448,6 +448,9 @@ type PersistentVolumeSource struct {
|
|||||||
// More info: https://releases.k8s.io/HEAD/examples/volumes/storageos/README.md
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/storageos/README.md
|
||||||
// +optional
|
// +optional
|
||||||
StorageOS *StorageOSPersistentVolumeSource `json:"storageos,omitempty" protobuf:"bytes,21,opt,name=storageos"`
|
StorageOS *StorageOSPersistentVolumeSource `json:"storageos,omitempty" protobuf:"bytes,21,opt,name=storageos"`
|
||||||
|
// CSI represents storage that handled by an external CSI driver
|
||||||
|
// +optional
|
||||||
|
CSI *CSIPersistentVolumeSource `json:"csi,omitempty" protobuf:"bytes,22,opt,name=csi"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -1621,6 +1624,23 @@ type LocalVolumeSource struct {
|
|||||||
Path string `json:"path" protobuf:"bytes,1,opt,name=path"`
|
Path string `json:"path" protobuf:"bytes,1,opt,name=path"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Represents storage that is managed by an external CSI volume driver
|
||||||
|
type CSIPersistentVolumeSource struct {
|
||||||
|
// Driver is the name of the driver to use for this volume.
|
||||||
|
// Required.
|
||||||
|
Driver string `json:"driver" protobuf:"bytes,1,opt,name=driver"`
|
||||||
|
|
||||||
|
// VolumeHandle is the unique volume name returned by the CSI volume
|
||||||
|
// plugin’s CreateVolume to refer to the volume on all subsequent calls.
|
||||||
|
// Required.
|
||||||
|
VolumeHandle string `json:"volumeHandle" protobuf:"bytes,2,opt,name=volumeHandle"`
|
||||||
|
|
||||||
|
// Optional: The value to pass to ControllerPublishVolumeRequest.
|
||||||
|
// Defaults to false (read/write).
|
||||||
|
// +optional
|
||||||
|
ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,3,opt,name=readOnly"`
|
||||||
|
}
|
||||||
|
|
||||||
// ContainerPort represents a network port in a single container.
|
// ContainerPort represents a network port in a single container.
|
||||||
type ContainerPort struct {
|
type ContainerPort struct {
|
||||||
// If specified, this must be an IANA_SVC_NAME and unique within the pod. Each
|
// If specified, this must be an IANA_SVC_NAME and unique within the pod. Each
|
||||||
|
Loading…
Reference in New Issue
Block a user