mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Merge pull request #55204 from vladimirvivien/k8s-csi-volume-source
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Kubernetes CSI - Persistent Volume Source Type **What this PR does / why we need it**: This PR is to track the addition of new API type `CSIPersistentVolumeSource` that will be used as PersistentVolume for storage sources managed by CSI drivers. **Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*: xref https://github.com/kubernetes/features/issues/178 **Special notes for your reviewer**: - Implements API `PersistentVolume` type `CSIPersistentVolumeSource` - Part of implementation for https://github.com/kubernetes/features/issues/178 - Designed at https://github.com/kubernetes/community/pull/1258 Other CSI Volume Plugin PRs: - Plugin Mounter/Unmounter https://github.com/kubernetes/kubernetes/pull/54529 - Plugin Attacher/Detacher https://github.com/kubernetes/kubernetes/pull/55809 **Release note**: ```release-note NONE ```
This commit is contained in:
		
							
								
								
									
										25
									
								
								api/openapi-spec/swagger.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										25
									
								
								api/openapi-spec/swagger.json
									
									
									
										generated
									
									
									
								
							@@ -73464,6 +73464,27 @@
 | 
			
		||||
     }
 | 
			
		||||
    ]
 | 
			
		||||
   },
 | 
			
		||||
   "io.k8s.api.core.v1.CSIPersistentVolumeSource": {
 | 
			
		||||
    "description": "Represents storage that is managed by an external CSI volume driver",
 | 
			
		||||
    "required": [
 | 
			
		||||
     "driver",
 | 
			
		||||
     "volumeHandle"
 | 
			
		||||
    ],
 | 
			
		||||
    "properties": {
 | 
			
		||||
     "driver": {
 | 
			
		||||
      "description": "Driver is the name of the driver to use for this volume. Required.",
 | 
			
		||||
      "type": "string"
 | 
			
		||||
     },
 | 
			
		||||
     "readOnly": {
 | 
			
		||||
      "description": "Optional: The value to pass to ControllerPublishVolumeRequest. Defaults to false (read/write).",
 | 
			
		||||
      "type": "boolean"
 | 
			
		||||
     },
 | 
			
		||||
     "volumeHandle": {
 | 
			
		||||
      "description": "VolumeHandle is the unique volume name returned by the CSI volume plugin’s CreateVolume to refer to the volume on all subsequent calls. Required.",
 | 
			
		||||
      "type": "string"
 | 
			
		||||
     }
 | 
			
		||||
    }
 | 
			
		||||
   },
 | 
			
		||||
   "io.k8s.api.core.v1.Capabilities": {
 | 
			
		||||
    "description": "Adds and removes POSIX capabilities from running containers.",
 | 
			
		||||
    "properties": {
 | 
			
		||||
@@ -75812,6 +75833,10 @@
 | 
			
		||||
      "description": "ClaimRef is part of a bi-directional binding between PersistentVolume and PersistentVolumeClaim. Expected to be non-nil when bound. claim.VolumeName is the authoritative bind between PV and PVC. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#binding",
 | 
			
		||||
      "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference"
 | 
			
		||||
     },
 | 
			
		||||
     "csi": {
 | 
			
		||||
      "description": "CSI represents storage that handled by an external CSI driver",
 | 
			
		||||
      "$ref": "#/definitions/io.k8s.api.core.v1.CSIPersistentVolumeSource"
 | 
			
		||||
     },
 | 
			
		||||
     "fc": {
 | 
			
		||||
      "description": "FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.",
 | 
			
		||||
      "$ref": "#/definitions/io.k8s.api.core.v1.FCVolumeSource"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								api/swagger-spec/v1.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										26
									
								
								api/swagger-spec/v1.json
									
									
									
										generated
									
									
									
								
							@@ -20592,6 +20592,10 @@
 | 
			
		||||
      "$ref": "v1.StorageOSPersistentVolumeSource",
 | 
			
		||||
      "description": "StorageOS represents a StorageOS volume that is attached to the kubelet's host machine and mounted into the pod More info: https://releases.k8s.io/HEAD/examples/volumes/storageos/README.md"
 | 
			
		||||
     },
 | 
			
		||||
     "csi": {
 | 
			
		||||
      "$ref": "v1.CSIPersistentVolumeSource",
 | 
			
		||||
      "description": "CSI represents storage that handled by an external CSI driver"
 | 
			
		||||
     },
 | 
			
		||||
     "accessModes": {
 | 
			
		||||
      "type": "array",
 | 
			
		||||
      "items": {
 | 
			
		||||
@@ -21250,6 +21254,28 @@
 | 
			
		||||
     }
 | 
			
		||||
    }
 | 
			
		||||
   },
 | 
			
		||||
   "v1.CSIPersistentVolumeSource": {
 | 
			
		||||
    "id": "v1.CSIPersistentVolumeSource",
 | 
			
		||||
    "description": "Represents storage that is managed by an external CSI volume driver",
 | 
			
		||||
    "required": [
 | 
			
		||||
     "driver",
 | 
			
		||||
     "volumeHandle"
 | 
			
		||||
    ],
 | 
			
		||||
    "properties": {
 | 
			
		||||
     "driver": {
 | 
			
		||||
      "type": "string",
 | 
			
		||||
      "description": "Driver is the name of the driver to use for this volume. Required."
 | 
			
		||||
     },
 | 
			
		||||
     "volumeHandle": {
 | 
			
		||||
      "type": "string",
 | 
			
		||||
      "description": "VolumeHandle is the unique volume name returned by the CSI volume plugin’s CreateVolume to refer to the volume on all subsequent calls. Required."
 | 
			
		||||
     },
 | 
			
		||||
     "readOnly": {
 | 
			
		||||
      "type": "boolean",
 | 
			
		||||
      "description": "Optional: The value to pass to ControllerPublishVolumeRequest. Defaults to false (read/write)."
 | 
			
		||||
     }
 | 
			
		||||
    }
 | 
			
		||||
   },
 | 
			
		||||
   "v1.PersistentVolumeStatus": {
 | 
			
		||||
    "id": "v1.PersistentVolumeStatus",
 | 
			
		||||
    "description": "PersistentVolumeStatus is the current status of a persistent volume.",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										55
									
								
								docs/api-reference/v1/definitions.html
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										55
									
								
								docs/api-reference/v1/definitions.html
									
									
									
										generated
									
									
									
								
							@@ -3651,6 +3651,54 @@ The resulting set of endpoints can be viewed as:<br>
 | 
			
		||||
</tbody>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
<div class="sect2">
 | 
			
		||||
<h3 id="_v1_csipersistentvolumesource">v1.CSIPersistentVolumeSource</h3>
 | 
			
		||||
<div class="paragraph">
 | 
			
		||||
<p>Represents storage that is managed by an external CSI volume driver</p>
 | 
			
		||||
</div>
 | 
			
		||||
<table class="tableblock frame-all grid-all" style="width:100%; ">
 | 
			
		||||
<colgroup>
 | 
			
		||||
<col style="width:20%;">
 | 
			
		||||
<col style="width:20%;">
 | 
			
		||||
<col style="width:20%;">
 | 
			
		||||
<col style="width:20%;">
 | 
			
		||||
<col style="width:20%;"> 
 | 
			
		||||
</colgroup>
 | 
			
		||||
<thead>
 | 
			
		||||
<tr>
 | 
			
		||||
<th class="tableblock halign-left valign-top">Name</th>
 | 
			
		||||
<th class="tableblock halign-left valign-top">Description</th>
 | 
			
		||||
<th class="tableblock halign-left valign-top">Required</th>
 | 
			
		||||
<th class="tableblock halign-left valign-top">Schema</th>
 | 
			
		||||
<th class="tableblock halign-left valign-top">Default</th>
 | 
			
		||||
</tr>
 | 
			
		||||
</thead>
 | 
			
		||||
<tbody>
 | 
			
		||||
<tr>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">driver</p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Driver is the name of the driver to use for this volume. Required.</p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"></td>
 | 
			
		||||
</tr>
 | 
			
		||||
<tr>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeHandle</p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">VolumeHandle is the unique volume name returned by the CSI volume plugin’s CreateVolume to refer to the volume on all subsequent calls. Required.</p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"></td>
 | 
			
		||||
</tr>
 | 
			
		||||
<tr>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">readOnly</p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Optional: The value to pass to ControllerPublishVolumeRequest. Defaults to false (read/write).</p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
 | 
			
		||||
</tr>
 | 
			
		||||
</tbody>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
<div class="sect2">
 | 
			
		||||
<h3 id="_v1_persistentvolumeclaimcondition">v1.PersistentVolumeClaimCondition</h3>
 | 
			
		||||
@@ -7745,6 +7793,13 @@ Examples:<br>
 | 
			
		||||
<td class="tableblock halign-left valign-top"></td>
 | 
			
		||||
</tr>
 | 
			
		||||
<tr>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">csi</p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">CSI represents storage that handled by an external CSI driver</p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_csipersistentvolumesource">v1.CSIPersistentVolumeSource</a></p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"></td>
 | 
			
		||||
</tr>
 | 
			
		||||
<tr>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">accessModes</p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">AccessModes contains all ways the volume can be mounted. More info: <a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes">https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes</a></p></td>
 | 
			
		||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
 | 
			
		||||
 
 | 
			
		||||
@@ -391,6 +391,9 @@ type PersistentVolumeSource struct {
 | 
			
		||||
	// More info: https://releases.k8s.io/HEAD/examples/volumes/storageos/README.md
 | 
			
		||||
	// +optional
 | 
			
		||||
	StorageOS *StorageOSPersistentVolumeSource
 | 
			
		||||
	// CSI (Container Storage Interface) represents storage that handled by an external CSI driver
 | 
			
		||||
	// +optional
 | 
			
		||||
	CSI *CSIPersistentVolumeSource
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PersistentVolumeClaimVolumeSource struct {
 | 
			
		||||
@@ -1503,6 +1506,23 @@ type LocalVolumeSource struct {
 | 
			
		||||
	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
 | 
			
		||||
type ContainerPort struct {
 | 
			
		||||
	// Optional: If specified, this must be an IANA_SVC_NAME  Each named port
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								pkg/apis/core/v1/zz_generated.conversion.go
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										28
									
								
								pkg/apis/core/v1/zz_generated.conversion.go
									
									
									
										generated
									
									
									
								
							@@ -55,6 +55,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
 | 
			
		||||
		Convert_core_AzureFileVolumeSource_To_v1_AzureFileVolumeSource,
 | 
			
		||||
		Convert_v1_Binding_To_core_Binding,
 | 
			
		||||
		Convert_core_Binding_To_v1_Binding,
 | 
			
		||||
		Convert_v1_CSIPersistentVolumeSource_To_core_CSIPersistentVolumeSource,
 | 
			
		||||
		Convert_core_CSIPersistentVolumeSource_To_v1_CSIPersistentVolumeSource,
 | 
			
		||||
		Convert_v1_Capabilities_To_core_Capabilities,
 | 
			
		||||
		Convert_core_Capabilities_To_v1_Capabilities,
 | 
			
		||||
		Convert_v1_CephFSPersistentVolumeSource_To_core_CephFSPersistentVolumeSource,
 | 
			
		||||
@@ -600,6 +602,30 @@ func Convert_core_Binding_To_v1_Binding(in *core.Binding, out *v1.Binding, s con
 | 
			
		||||
	return autoConvert_core_Binding_To_v1_Binding(in, out, s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func autoConvert_v1_CSIPersistentVolumeSource_To_core_CSIPersistentVolumeSource(in *v1.CSIPersistentVolumeSource, out *core.CSIPersistentVolumeSource, s conversion.Scope) error {
 | 
			
		||||
	out.Driver = in.Driver
 | 
			
		||||
	out.VolumeHandle = in.VolumeHandle
 | 
			
		||||
	out.ReadOnly = in.ReadOnly
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert_v1_CSIPersistentVolumeSource_To_core_CSIPersistentVolumeSource is an autogenerated conversion function.
 | 
			
		||||
func Convert_v1_CSIPersistentVolumeSource_To_core_CSIPersistentVolumeSource(in *v1.CSIPersistentVolumeSource, out *core.CSIPersistentVolumeSource, s conversion.Scope) error {
 | 
			
		||||
	return autoConvert_v1_CSIPersistentVolumeSource_To_core_CSIPersistentVolumeSource(in, out, s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func autoConvert_core_CSIPersistentVolumeSource_To_v1_CSIPersistentVolumeSource(in *core.CSIPersistentVolumeSource, out *v1.CSIPersistentVolumeSource, s conversion.Scope) error {
 | 
			
		||||
	out.Driver = in.Driver
 | 
			
		||||
	out.VolumeHandle = in.VolumeHandle
 | 
			
		||||
	out.ReadOnly = in.ReadOnly
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert_core_CSIPersistentVolumeSource_To_v1_CSIPersistentVolumeSource is an autogenerated conversion function.
 | 
			
		||||
func Convert_core_CSIPersistentVolumeSource_To_v1_CSIPersistentVolumeSource(in *core.CSIPersistentVolumeSource, out *v1.CSIPersistentVolumeSource, s conversion.Scope) error {
 | 
			
		||||
	return autoConvert_core_CSIPersistentVolumeSource_To_v1_CSIPersistentVolumeSource(in, out, s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func autoConvert_v1_Capabilities_To_core_Capabilities(in *v1.Capabilities, out *core.Capabilities, s conversion.Scope) error {
 | 
			
		||||
	out.Add = *(*[]core.Capability)(unsafe.Pointer(&in.Add))
 | 
			
		||||
	out.Drop = *(*[]core.Capability)(unsafe.Pointer(&in.Drop))
 | 
			
		||||
@@ -3144,6 +3170,7 @@ func autoConvert_v1_PersistentVolumeSource_To_core_PersistentVolumeSource(in *v1
 | 
			
		||||
	out.ScaleIO = (*core.ScaleIOPersistentVolumeSource)(unsafe.Pointer(in.ScaleIO))
 | 
			
		||||
	out.Local = (*core.LocalVolumeSource)(unsafe.Pointer(in.Local))
 | 
			
		||||
	out.StorageOS = (*core.StorageOSPersistentVolumeSource)(unsafe.Pointer(in.StorageOS))
 | 
			
		||||
	out.CSI = (*core.CSIPersistentVolumeSource)(unsafe.Pointer(in.CSI))
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -3174,6 +3201,7 @@ func autoConvert_core_PersistentVolumeSource_To_v1_PersistentVolumeSource(in *co
 | 
			
		||||
	out.ScaleIO = (*v1.ScaleIOPersistentVolumeSource)(unsafe.Pointer(in.ScaleIO))
 | 
			
		||||
	out.Local = (*v1.LocalVolumeSource)(unsafe.Pointer(in.Local))
 | 
			
		||||
	out.StorageOS = (*v1.StorageOSPersistentVolumeSource)(unsafe.Pointer(in.StorageOS))
 | 
			
		||||
	out.CSI = (*v1.CSIPersistentVolumeSource)(unsafe.Pointer(in.CSI))
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1318,6 +1318,24 @@ func validateStorageOSPersistentVolumeSource(storageos *core.StorageOSPersistent
 | 
			
		||||
	return allErrs
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func validateCSIPersistentVolumeSource(csi *core.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
 | 
			
		||||
// PersistentVolumeName object.
 | 
			
		||||
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 {
 | 
			
		||||
		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
 | 
			
		||||
func newInt32(val int) *int32 {
 | 
			
		||||
	p := new(int32)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								pkg/apis/core/zz_generated.deepcopy.go
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										25
									
								
								pkg/apis/core/zz_generated.deepcopy.go
									
									
									
										generated
									
									
									
								
							@@ -246,6 +246,22 @@ func (in *Binding) DeepCopyObject() runtime.Object {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
			
		||||
func (in *CSIPersistentVolumeSource) DeepCopyInto(out *CSIPersistentVolumeSource) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSIPersistentVolumeSource.
 | 
			
		||||
func (in *CSIPersistentVolumeSource) DeepCopy() *CSIPersistentVolumeSource {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(CSIPersistentVolumeSource)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
			
		||||
func (in *Capabilities) DeepCopyInto(out *Capabilities) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
@@ -3159,6 +3175,15 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) {
 | 
			
		||||
			(*in).DeepCopyInto(*out)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if in.CSI != nil {
 | 
			
		||||
		in, out := &in.CSI, &out.CSI
 | 
			
		||||
		if *in == nil {
 | 
			
		||||
			*out = nil
 | 
			
		||||
		} else {
 | 
			
		||||
			*out = new(CSIPersistentVolumeSource)
 | 
			
		||||
			**out = **in
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -919,6 +919,7 @@ var (
 | 
			
		||||
	Projected             FSType = "projected"
 | 
			
		||||
	PortworxVolume        FSType = "portworxVolume"
 | 
			
		||||
	ScaleIO               FSType = "scaleIO"
 | 
			
		||||
	CSI                   FSType = "csi"
 | 
			
		||||
	All                   FSType = "*"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -181,6 +181,12 @@ const (
 | 
			
		||||
	//
 | 
			
		||||
	// Extend the default scheduler to be aware of PV topology and handle PV binding
 | 
			
		||||
	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() {
 | 
			
		||||
@@ -215,6 +221,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS
 | 
			
		||||
	ServiceNodeExclusion:                        {Default: false, PreRelease: utilfeature.Alpha},
 | 
			
		||||
	MountContainers:                             {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
 | 
			
		||||
	// unintentionally on either side:
 | 
			
		||||
 
 | 
			
		||||
@@ -1073,6 +1073,14 @@ func printFlockerVolumeSource(flocker *api.FlockerVolumeSource, w PrefixWriter)
 | 
			
		||||
		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 {
 | 
			
		||||
	clientset.Interface
 | 
			
		||||
}
 | 
			
		||||
@@ -1156,6 +1164,8 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) (
 | 
			
		||||
			printFlexVolumeSource(pv.Spec.FlexVolume, w)
 | 
			
		||||
		case pv.Spec.Flocker != nil:
 | 
			
		||||
			printFlockerVolumeSource(pv.Spec.Flocker, w)
 | 
			
		||||
		case pv.Spec.CSI != nil:
 | 
			
		||||
			printCSIPersistentVolumeSource(pv.Spec.CSI, w)
 | 
			
		||||
		default:
 | 
			
		||||
			w.Write(LEVEL_1, "<unknown>\n")
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -67,6 +67,7 @@ func GetAllFSTypesAsSet() sets.String {
 | 
			
		||||
		string(extensions.Projected),
 | 
			
		||||
		string(extensions.PortworxVolume),
 | 
			
		||||
		string(extensions.ScaleIO),
 | 
			
		||||
		string(extensions.CSI),
 | 
			
		||||
	)
 | 
			
		||||
	return fstypes
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -108,6 +108,7 @@ filegroup(
 | 
			
		||||
        "//pkg/volume/cephfs:all-srcs",
 | 
			
		||||
        "//pkg/volume/cinder:all-srcs",
 | 
			
		||||
        "//pkg/volume/configmap:all-srcs",
 | 
			
		||||
        "//pkg/volume/csi:all-srcs",
 | 
			
		||||
        "//pkg/volume/downwardapi:all-srcs",
 | 
			
		||||
        "//pkg/volume/empty_dir:all-srcs",
 | 
			
		||||
        "//pkg/volume/fc:all-srcs",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										33
									
								
								pkg/volume/csi/BUILD
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								pkg/volume/csi/BUILD
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
 | 
			
		||||
 | 
			
		||||
go_library(
 | 
			
		||||
    name = "go_default_library",
 | 
			
		||||
    srcs = [
 | 
			
		||||
        "csi_attacher.go",
 | 
			
		||||
        "csi_mounter.go",
 | 
			
		||||
        "csi_plugin.go",
 | 
			
		||||
    ],
 | 
			
		||||
    importpath = "k8s.io/kubernetes/pkg/volume/csi",
 | 
			
		||||
    visibility = ["//visibility:public"],
 | 
			
		||||
    deps = [
 | 
			
		||||
        "//pkg/util/mount:go_default_library",
 | 
			
		||||
        "//pkg/util/strings:go_default_library",
 | 
			
		||||
        "//pkg/volume:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/api/core/v1:go_default_library",
 | 
			
		||||
        "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
filegroup(
 | 
			
		||||
    name = "package-srcs",
 | 
			
		||||
    srcs = glob(["**"]),
 | 
			
		||||
    tags = ["automanaged"],
 | 
			
		||||
    visibility = ["//visibility:private"],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
filegroup(
 | 
			
		||||
    name = "all-srcs",
 | 
			
		||||
    srcs = [":package-srcs"],
 | 
			
		||||
    tags = ["automanaged"],
 | 
			
		||||
    visibility = ["//visibility:public"],
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										2671
									
								
								staging/src/k8s.io/api/core/v1/generated.pb.go
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2671
									
								
								staging/src/k8s.io/api/core/v1/generated.pb.go
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -170,6 +170,23 @@ message Binding {
 | 
			
		||||
  optional ObjectReference target = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Represents storage that is managed by an external CSI volume driver
 | 
			
		||||
message CSIPersistentVolumeSource {
 | 
			
		||||
  // Driver is the name of the driver to use for this volume.
 | 
			
		||||
  // Required.
 | 
			
		||||
  optional string driver = 1;
 | 
			
		||||
 | 
			
		||||
  // VolumeHandle is the unique volume name returned by the CSI volume
 | 
			
		||||
  // plugin’s CreateVolume to refer to the volume on all subsequent calls.
 | 
			
		||||
  // Required.
 | 
			
		||||
  optional string volumeHandle = 2;
 | 
			
		||||
 | 
			
		||||
  // Optional: The value to pass to ControllerPublishVolumeRequest.
 | 
			
		||||
  // Defaults to false (read/write).
 | 
			
		||||
  // +optional
 | 
			
		||||
  optional bool readOnly = 3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Adds and removes POSIX capabilities from running containers.
 | 
			
		||||
message Capabilities {
 | 
			
		||||
  // Added capabilities
 | 
			
		||||
@@ -2356,6 +2373,10 @@ message PersistentVolumeSource {
 | 
			
		||||
  // More info: https://releases.k8s.io/HEAD/examples/volumes/storageos/README.md
 | 
			
		||||
  // +optional
 | 
			
		||||
  optional StorageOSPersistentVolumeSource storageos = 21;
 | 
			
		||||
 | 
			
		||||
  // CSI represents storage that handled by an external CSI driver
 | 
			
		||||
  // +optional
 | 
			
		||||
  optional CSIPersistentVolumeSource csi = 22;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PersistentVolumeSpec is the specification of a persistent volume.
 | 
			
		||||
 
 | 
			
		||||
@@ -448,6 +448,9 @@ type PersistentVolumeSource struct {
 | 
			
		||||
	// More info: https://releases.k8s.io/HEAD/examples/volumes/storageos/README.md
 | 
			
		||||
	// +optional
 | 
			
		||||
	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 (
 | 
			
		||||
@@ -1621,6 +1624,23 @@ type LocalVolumeSource struct {
 | 
			
		||||
	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.
 | 
			
		||||
type ContainerPort struct {
 | 
			
		||||
	// If specified, this must be an IANA_SVC_NAME and unique within the pod. Each
 | 
			
		||||
 
 | 
			
		||||
@@ -116,6 +116,17 @@ func (Binding) SwaggerDoc() map[string]string {
 | 
			
		||||
	return map_Binding
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var map_CSIPersistentVolumeSource = map[string]string{
 | 
			
		||||
	"":             "Represents storage that is managed by an external CSI volume driver",
 | 
			
		||||
	"driver":       "Driver is the name of the driver to use for this volume. Required.",
 | 
			
		||||
	"volumeHandle": "VolumeHandle is the unique volume name returned by the CSI volume plugin’s CreateVolume to refer to the volume on all subsequent calls. Required.",
 | 
			
		||||
	"readOnly":     "Optional: The value to pass to ControllerPublishVolumeRequest. Defaults to false (read/write).",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (CSIPersistentVolumeSource) SwaggerDoc() map[string]string {
 | 
			
		||||
	return map_CSIPersistentVolumeSource
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var map_Capabilities = map[string]string{
 | 
			
		||||
	"":     "Adds and removes POSIX capabilities from running containers.",
 | 
			
		||||
	"add":  "Added capabilities",
 | 
			
		||||
@@ -1212,6 +1223,7 @@ var map_PersistentVolumeSource = map[string]string{
 | 
			
		||||
	"scaleIO":              "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.",
 | 
			
		||||
	"local":                "Local represents directly-attached storage with node affinity",
 | 
			
		||||
	"storageos":            "StorageOS represents a StorageOS volume that is attached to the kubelet's host machine and mounted into the pod More info: https://releases.k8s.io/HEAD/examples/volumes/storageos/README.md",
 | 
			
		||||
	"csi":                  "CSI represents storage that handled by an external CSI driver",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (PersistentVolumeSource) SwaggerDoc() map[string]string {
 | 
			
		||||
 
 | 
			
		||||
@@ -246,6 +246,22 @@ func (in *Binding) DeepCopyObject() runtime.Object {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
			
		||||
func (in *CSIPersistentVolumeSource) DeepCopyInto(out *CSIPersistentVolumeSource) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSIPersistentVolumeSource.
 | 
			
		||||
func (in *CSIPersistentVolumeSource) DeepCopy() *CSIPersistentVolumeSource {
 | 
			
		||||
	if in == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	out := new(CSIPersistentVolumeSource)
 | 
			
		||||
	in.DeepCopyInto(out)
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
			
		||||
func (in *Capabilities) DeepCopyInto(out *Capabilities) {
 | 
			
		||||
	*out = *in
 | 
			
		||||
@@ -3145,6 +3161,15 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) {
 | 
			
		||||
			(*in).DeepCopyInto(*out)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if in.CSI != nil {
 | 
			
		||||
		in, out := &in.CSI, &out.CSI
 | 
			
		||||
		if *in == nil {
 | 
			
		||||
			*out = nil
 | 
			
		||||
		} else {
 | 
			
		||||
			*out = new(CSIPersistentVolumeSource)
 | 
			
		||||
			**out = **in
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user