mirror of https://github.com/k3s-io/k3s
Merge pull request #71167 from msau42/block-beta
Promote raw block volume support to betapull/58/head
commit
ec2e767e59
|
@ -84268,7 +84268,7 @@
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"volumeDevices": {
|
"volumeDevices": {
|
||||||
"description": "volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future.",
|
"description": "volumeDevices is the list of block devices to be used by the container. This is a beta feature.",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/io.k8s.api.core.v1.VolumeDevice"
|
"$ref": "#/definitions/io.k8s.api.core.v1.VolumeDevice"
|
||||||
|
@ -86221,7 +86221,7 @@
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"volumeMode": {
|
"volumeMode": {
|
||||||
"description": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is an alpha feature and may change in the future.",
|
"description": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is a beta feature.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"volumeName": {
|
"volumeName": {
|
||||||
|
@ -86437,7 +86437,7 @@
|
||||||
"$ref": "#/definitions/io.k8s.api.core.v1.StorageOSPersistentVolumeSource"
|
"$ref": "#/definitions/io.k8s.api.core.v1.StorageOSPersistentVolumeSource"
|
||||||
},
|
},
|
||||||
"volumeMode": {
|
"volumeMode": {
|
||||||
"description": "volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec. This is an alpha feature and may change in the future.",
|
"description": "volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec. This is a beta feature.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"vsphereVolume": {
|
"vsphereVolume": {
|
||||||
|
|
|
@ -8227,7 +8227,7 @@
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "v1.VolumeDevice"
|
"$ref": "v1.VolumeDevice"
|
||||||
},
|
},
|
||||||
"description": "volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future."
|
"description": "volumeDevices is the list of block devices to be used by the container. This is a beta feature."
|
||||||
},
|
},
|
||||||
"livenessProbe": {
|
"livenessProbe": {
|
||||||
"$ref": "v1.Probe",
|
"$ref": "v1.Probe",
|
||||||
|
@ -9796,7 +9796,7 @@
|
||||||
},
|
},
|
||||||
"volumeMode": {
|
"volumeMode": {
|
||||||
"$ref": "v1.PersistentVolumeMode",
|
"$ref": "v1.PersistentVolumeMode",
|
||||||
"description": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is an alpha feature and may change in the future."
|
"description": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is a beta feature."
|
||||||
},
|
},
|
||||||
"dataSource": {
|
"dataSource": {
|
||||||
"$ref": "v1.TypedLocalObjectReference",
|
"$ref": "v1.TypedLocalObjectReference",
|
||||||
|
|
|
@ -5739,7 +5739,7 @@
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "v1.VolumeDevice"
|
"$ref": "v1.VolumeDevice"
|
||||||
},
|
},
|
||||||
"description": "volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future."
|
"description": "volumeDevices is the list of block devices to be used by the container. This is a beta feature."
|
||||||
},
|
},
|
||||||
"livenessProbe": {
|
"livenessProbe": {
|
||||||
"$ref": "v1.Probe",
|
"$ref": "v1.Probe",
|
||||||
|
@ -6982,7 +6982,7 @@
|
||||||
},
|
},
|
||||||
"volumeMode": {
|
"volumeMode": {
|
||||||
"$ref": "v1.PersistentVolumeMode",
|
"$ref": "v1.PersistentVolumeMode",
|
||||||
"description": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is an alpha feature and may change in the future."
|
"description": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is a beta feature."
|
||||||
},
|
},
|
||||||
"dataSource": {
|
"dataSource": {
|
||||||
"$ref": "v1.TypedLocalObjectReference",
|
"$ref": "v1.TypedLocalObjectReference",
|
||||||
|
|
|
@ -8227,7 +8227,7 @@
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "v1.VolumeDevice"
|
"$ref": "v1.VolumeDevice"
|
||||||
},
|
},
|
||||||
"description": "volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future."
|
"description": "volumeDevices is the list of block devices to be used by the container. This is a beta feature."
|
||||||
},
|
},
|
||||||
"livenessProbe": {
|
"livenessProbe": {
|
||||||
"$ref": "v1.Probe",
|
"$ref": "v1.Probe",
|
||||||
|
@ -9800,7 +9800,7 @@
|
||||||
},
|
},
|
||||||
"volumeMode": {
|
"volumeMode": {
|
||||||
"$ref": "v1.PersistentVolumeMode",
|
"$ref": "v1.PersistentVolumeMode",
|
||||||
"description": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is an alpha feature and may change in the future."
|
"description": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is a beta feature."
|
||||||
},
|
},
|
||||||
"dataSource": {
|
"dataSource": {
|
||||||
"$ref": "v1.TypedLocalObjectReference",
|
"$ref": "v1.TypedLocalObjectReference",
|
||||||
|
|
|
@ -2923,7 +2923,7 @@
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "v1.VolumeDevice"
|
"$ref": "v1.VolumeDevice"
|
||||||
},
|
},
|
||||||
"description": "volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future."
|
"description": "volumeDevices is the list of block devices to be used by the container. This is a beta feature."
|
||||||
},
|
},
|
||||||
"livenessProbe": {
|
"livenessProbe": {
|
||||||
"$ref": "v1.Probe",
|
"$ref": "v1.Probe",
|
||||||
|
|
|
@ -2978,7 +2978,7 @@
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "v1.VolumeDevice"
|
"$ref": "v1.VolumeDevice"
|
||||||
},
|
},
|
||||||
"description": "volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future."
|
"description": "volumeDevices is the list of block devices to be used by the container. This is a beta feature."
|
||||||
},
|
},
|
||||||
"livenessProbe": {
|
"livenessProbe": {
|
||||||
"$ref": "v1.Probe",
|
"$ref": "v1.Probe",
|
||||||
|
|
|
@ -2978,7 +2978,7 @@
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "v1.VolumeDevice"
|
"$ref": "v1.VolumeDevice"
|
||||||
},
|
},
|
||||||
"description": "volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future."
|
"description": "volumeDevices is the list of block devices to be used by the container. This is a beta feature."
|
||||||
},
|
},
|
||||||
"livenessProbe": {
|
"livenessProbe": {
|
||||||
"$ref": "v1.Probe",
|
"$ref": "v1.Probe",
|
||||||
|
|
|
@ -8923,7 +8923,7 @@
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "v1.VolumeDevice"
|
"$ref": "v1.VolumeDevice"
|
||||||
},
|
},
|
||||||
"description": "volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future."
|
"description": "volumeDevices is the list of block devices to be used by the container. This is a beta feature."
|
||||||
},
|
},
|
||||||
"livenessProbe": {
|
"livenessProbe": {
|
||||||
"$ref": "v1.Probe",
|
"$ref": "v1.Probe",
|
||||||
|
|
|
@ -19987,7 +19987,7 @@
|
||||||
},
|
},
|
||||||
"volumeMode": {
|
"volumeMode": {
|
||||||
"$ref": "v1.PersistentVolumeMode",
|
"$ref": "v1.PersistentVolumeMode",
|
||||||
"description": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is an alpha feature and may change in the future."
|
"description": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is a beta feature."
|
||||||
},
|
},
|
||||||
"dataSource": {
|
"dataSource": {
|
||||||
"$ref": "v1.TypedLocalObjectReference",
|
"$ref": "v1.TypedLocalObjectReference",
|
||||||
|
@ -20320,7 +20320,7 @@
|
||||||
},
|
},
|
||||||
"volumeMode": {
|
"volumeMode": {
|
||||||
"$ref": "v1.PersistentVolumeMode",
|
"$ref": "v1.PersistentVolumeMode",
|
||||||
"description": "volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec. This is an alpha feature and may change in the future."
|
"description": "volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec. This is a beta feature."
|
||||||
},
|
},
|
||||||
"nodeAffinity": {
|
"nodeAffinity": {
|
||||||
"$ref": "v1.VolumeNodeAffinity",
|
"$ref": "v1.VolumeNodeAffinity",
|
||||||
|
@ -22143,7 +22143,7 @@
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "v1.VolumeDevice"
|
"$ref": "v1.VolumeDevice"
|
||||||
},
|
},
|
||||||
"description": "volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future."
|
"description": "volumeDevices is the list of block devices to be used by the container. This is a beta feature."
|
||||||
},
|
},
|
||||||
"livenessProbe": {
|
"livenessProbe": {
|
||||||
"$ref": "v1.Probe",
|
"$ref": "v1.Probe",
|
||||||
|
|
|
@ -1012,7 +1012,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is an alpha feature and may change in the future.</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is a beta feature.</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">false</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_persistentvolumemode">v1.PersistentVolumeMode</a></p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_persistentvolumemode">v1.PersistentVolumeMode</a></p></td>
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
@ -5718,7 +5718,7 @@ Examples:<br>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future.</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices is the list of block devices to be used by the container. This is a beta feature.</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">false</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_volumedevice">v1.VolumeDevice</a> array</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_volumedevice">v1.VolumeDevice</a> array</p></td>
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
|
|
@ -1040,7 +1040,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is an alpha feature and may change in the future.</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is a beta feature.</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">false</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_persistentvolumemode">v1.PersistentVolumeMode</a></p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_persistentvolumemode">v1.PersistentVolumeMode</a></p></td>
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
@ -5853,7 +5853,7 @@ Examples:<br>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future.</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices is the list of block devices to be used by the container. This is a beta feature.</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">false</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_volumedevice">v1.VolumeDevice</a> array</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_volumedevice">v1.VolumeDevice</a> array</p></td>
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
|
|
@ -987,7 +987,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is an alpha feature and may change in the future.</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is a beta feature.</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">false</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_persistentvolumemode">v1.PersistentVolumeMode</a></p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_persistentvolumemode">v1.PersistentVolumeMode</a></p></td>
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
@ -6187,7 +6187,7 @@ Examples:<br>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future.</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices is the list of block devices to be used by the container. This is a beta feature.</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">false</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_volumedevice">v1.VolumeDevice</a> array</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_volumedevice">v1.VolumeDevice</a> array</p></td>
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
|
|
@ -4610,7 +4610,7 @@ Examples:<br>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future.</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices is the list of block devices to be used by the container. This is a beta feature.</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">false</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_volumedevice">v1.VolumeDevice</a> array</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_volumedevice">v1.VolumeDevice</a> array</p></td>
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
|
|
@ -4761,7 +4761,7 @@ Examples:<br>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future.</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices is the list of block devices to be used by the container. This is a beta feature.</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">false</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_volumedevice">v1.VolumeDevice</a> array</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_volumedevice">v1.VolumeDevice</a> array</p></td>
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
|
|
@ -4617,7 +4617,7 @@ Examples:<br>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future.</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices is the list of block devices to be used by the container. This is a beta feature.</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">false</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_volumedevice">v1.VolumeDevice</a> array</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_volumedevice">v1.VolumeDevice</a> array</p></td>
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
|
|
@ -6565,7 +6565,7 @@ If PodSelector is also set, then the NetworkPolicyPeer as a whole selects the Po
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future.</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices is the list of block devices to be used by the container. This is a beta feature.</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">false</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_volumedevice">v1.VolumeDevice</a> array</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_volumedevice">v1.VolumeDevice</a> array</p></td>
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
|
|
@ -689,7 +689,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is an alpha feature and may change in the future.</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is a beta feature.</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">false</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_persistentvolumemode">v1.PersistentVolumeMode</a></p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_persistentvolumemode">v1.PersistentVolumeMode</a></p></td>
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
@ -4282,7 +4282,7 @@ Examples:<br>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec. This is an alpha feature and may change in the future.</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec. This is a beta feature.</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">false</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_persistentvolumemode">v1.PersistentVolumeMode</a></p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_persistentvolumemode">v1.PersistentVolumeMode</a></p></td>
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
@ -10595,7 +10595,7 @@ More info: <a href="https://kubernetes.io/docs/concepts/workloads/pods/pod-lifec
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future.</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">volumeDevices is the list of block devices to be used by the container. This is a beta feature.</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">false</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_volumedevice">v1.VolumeDevice</a> array</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_volumedevice">v1.VolumeDevice</a> array</p></td>
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
|
|
@ -403,11 +403,15 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
|
||||||
pv.Status.Message = c.RandString()
|
pv.Status.Message = c.RandString()
|
||||||
reclamationPolicies := []core.PersistentVolumeReclaimPolicy{core.PersistentVolumeReclaimRecycle, core.PersistentVolumeReclaimRetain}
|
reclamationPolicies := []core.PersistentVolumeReclaimPolicy{core.PersistentVolumeReclaimRecycle, core.PersistentVolumeReclaimRetain}
|
||||||
pv.Spec.PersistentVolumeReclaimPolicy = reclamationPolicies[c.Rand.Intn(len(reclamationPolicies))]
|
pv.Spec.PersistentVolumeReclaimPolicy = reclamationPolicies[c.Rand.Intn(len(reclamationPolicies))]
|
||||||
|
volumeModes := []core.PersistentVolumeMode{core.PersistentVolumeFilesystem, core.PersistentVolumeBlock}
|
||||||
|
pv.Spec.VolumeMode = &volumeModes[c.Rand.Intn(len(volumeModes))]
|
||||||
},
|
},
|
||||||
func(pvc *core.PersistentVolumeClaim, c fuzz.Continue) {
|
func(pvc *core.PersistentVolumeClaim, c fuzz.Continue) {
|
||||||
c.FuzzNoCustom(pvc) // fuzz self without calling this function again
|
c.FuzzNoCustom(pvc) // fuzz self without calling this function again
|
||||||
types := []core.PersistentVolumeClaimPhase{core.ClaimBound, core.ClaimPending, core.ClaimLost}
|
types := []core.PersistentVolumeClaimPhase{core.ClaimBound, core.ClaimPending, core.ClaimLost}
|
||||||
pvc.Status.Phase = types[c.Rand.Intn(len(types))]
|
pvc.Status.Phase = types[c.Rand.Intn(len(types))]
|
||||||
|
volumeModes := []core.PersistentVolumeMode{core.PersistentVolumeFilesystem, core.PersistentVolumeBlock}
|
||||||
|
pvc.Spec.VolumeMode = &volumeModes[c.Rand.Intn(len(volumeModes))]
|
||||||
},
|
},
|
||||||
func(obj *core.AzureDiskVolumeSource, c fuzz.Continue) {
|
func(obj *core.AzureDiskVolumeSource, c fuzz.Continue) {
|
||||||
if obj.CachingMode == nil {
|
if obj.CachingMode == nil {
|
||||||
|
|
|
@ -298,7 +298,7 @@ type PersistentVolumeSpec struct {
|
||||||
MountOptions []string
|
MountOptions []string
|
||||||
// volumeMode defines if a volume is intended to be used with a formatted filesystem
|
// volumeMode defines if a volume is intended to be used with a formatted filesystem
|
||||||
// or to remain in raw block state. Value of Filesystem is implied when not included in spec.
|
// or to remain in raw block state. Value of Filesystem is implied when not included in spec.
|
||||||
// This is an alpha feature and may change in the future.
|
// This is a beta feature.
|
||||||
// +optional
|
// +optional
|
||||||
VolumeMode *PersistentVolumeMode
|
VolumeMode *PersistentVolumeMode
|
||||||
// NodeAffinity defines constraints that limit what nodes this volume can be accessed from.
|
// NodeAffinity defines constraints that limit what nodes this volume can be accessed from.
|
||||||
|
@ -410,7 +410,7 @@ type PersistentVolumeClaimSpec struct {
|
||||||
StorageClassName *string
|
StorageClassName *string
|
||||||
// volumeMode defines what type of volume is required by the claim.
|
// volumeMode defines what type of volume is required by the claim.
|
||||||
// Value of Filesystem is implied when not included in claim spec.
|
// Value of Filesystem is implied when not included in claim spec.
|
||||||
// This is an alpha feature and may change in the future.
|
// This is a beta feature.
|
||||||
// +optional
|
// +optional
|
||||||
VolumeMode *PersistentVolumeMode
|
VolumeMode *PersistentVolumeMode
|
||||||
// This field requires the VolumeSnapshotDataSource alpha feature gate to be
|
// This field requires the VolumeSnapshotDataSource alpha feature gate to be
|
||||||
|
@ -1968,7 +1968,7 @@ type Container struct {
|
||||||
// +optional
|
// +optional
|
||||||
VolumeMounts []VolumeMount
|
VolumeMounts []VolumeMount
|
||||||
// volumeDevices is the list of block devices to be used by the container.
|
// volumeDevices is the list of block devices to be used by the container.
|
||||||
// This is an alpha feature and may change in the future.
|
// This is a beta feature.
|
||||||
// +optional
|
// +optional
|
||||||
VolumeDevices []VolumeDevice
|
VolumeDevices []VolumeDevice
|
||||||
// +optional
|
// +optional
|
||||||
|
|
|
@ -27,8 +27,10 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
|
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
corev1 "k8s.io/kubernetes/pkg/apis/core/v1"
|
corev1 "k8s.io/kubernetes/pkg/apis/core/v1"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
utilpointer "k8s.io/utils/pointer"
|
utilpointer "k8s.io/utils/pointer"
|
||||||
|
|
||||||
// enforce that all types are installed
|
// enforce that all types are installed
|
||||||
|
@ -803,6 +805,7 @@ func TestSetDefaultSecret(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetDefaultPersistentVolume(t *testing.T) {
|
func TestSetDefaultPersistentVolume(t *testing.T) {
|
||||||
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)()
|
||||||
pv := &v1.PersistentVolume{}
|
pv := &v1.PersistentVolume{}
|
||||||
obj2 := roundTrip(t, runtime.Object(pv))
|
obj2 := roundTrip(t, runtime.Object(pv))
|
||||||
pv2 := obj2.(*v1.PersistentVolume)
|
pv2 := obj2.(*v1.PersistentVolume)
|
||||||
|
@ -822,10 +825,7 @@ func TestSetDefaultPersistentVolume(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// When feature gate is enabled, field should be defaulted
|
// When feature gate is enabled, field should be defaulted
|
||||||
err := utilfeature.DefaultFeatureGate.Set("BlockVolume=true")
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to enable feature gate for BlockVolume: %v", err)
|
|
||||||
}
|
|
||||||
obj3 := roundTrip(t, runtime.Object(pv)).(*v1.PersistentVolume)
|
obj3 := roundTrip(t, runtime.Object(pv)).(*v1.PersistentVolume)
|
||||||
outputMode3 := obj3.Spec.VolumeMode
|
outputMode3 := obj3.Spec.VolumeMode
|
||||||
|
|
||||||
|
@ -834,15 +834,10 @@ func TestSetDefaultPersistentVolume(t *testing.T) {
|
||||||
} else if *outputMode3 != defaultMode {
|
} else if *outputMode3 != defaultMode {
|
||||||
t.Errorf("Expected VolumeMode to be defaulted to: %+v, got: %+v", defaultMode, outputMode3)
|
t.Errorf("Expected VolumeMode to be defaulted to: %+v, got: %+v", defaultMode, outputMode3)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = utilfeature.DefaultFeatureGate.Set("BlockVolume=false")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to disable feature gate for BlockVolume: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetDefaultPersistentVolumeClaim(t *testing.T) {
|
func TestSetDefaultPersistentVolumeClaim(t *testing.T) {
|
||||||
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)()
|
||||||
pvc := &v1.PersistentVolumeClaim{}
|
pvc := &v1.PersistentVolumeClaim{}
|
||||||
obj2 := roundTrip(t, runtime.Object(pvc))
|
obj2 := roundTrip(t, runtime.Object(pvc))
|
||||||
pvc2 := obj2.(*v1.PersistentVolumeClaim)
|
pvc2 := obj2.(*v1.PersistentVolumeClaim)
|
||||||
|
@ -859,10 +854,7 @@ func TestSetDefaultPersistentVolumeClaim(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// When feature gate is enabled, field should be defaulted
|
// When feature gate is enabled, field should be defaulted
|
||||||
err := utilfeature.DefaultFeatureGate.Set("BlockVolume=true")
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to enable feature gate for BlockVolume: %v", err)
|
|
||||||
}
|
|
||||||
obj3 := roundTrip(t, runtime.Object(pvc)).(*v1.PersistentVolumeClaim)
|
obj3 := roundTrip(t, runtime.Object(pvc)).(*v1.PersistentVolumeClaim)
|
||||||
outputMode3 := obj3.Spec.VolumeMode
|
outputMode3 := obj3.Spec.VolumeMode
|
||||||
|
|
||||||
|
@ -871,11 +863,6 @@ func TestSetDefaultPersistentVolumeClaim(t *testing.T) {
|
||||||
} else if *outputMode3 != defaultMode {
|
} else if *outputMode3 != defaultMode {
|
||||||
t.Errorf("Expected VolumeMode to be defaulted to: %+v, got: %+v", defaultMode, outputMode3)
|
t.Errorf("Expected VolumeMode to be defaulted to: %+v, got: %+v", defaultMode, outputMode3)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = utilfeature.DefaultFeatureGate.Set("BlockVolume=false")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to disable feature gate for BlockVolume: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetDefaulEndpointsProtocol(t *testing.T) {
|
func TestSetDefaulEndpointsProtocol(t *testing.T) {
|
||||||
|
|
|
@ -66,9 +66,11 @@ func testVolume(name string, namespace string, spec core.PersistentVolumeSpec) *
|
||||||
|
|
||||||
func TestValidatePersistentVolumes(t *testing.T) {
|
func TestValidatePersistentVolumes(t *testing.T) {
|
||||||
validMode := core.PersistentVolumeFilesystem
|
validMode := core.PersistentVolumeFilesystem
|
||||||
|
invalidMode := core.PersistentVolumeMode("fakeVolumeMode")
|
||||||
scenarios := map[string]struct {
|
scenarios := map[string]struct {
|
||||||
isExpectedFailure bool
|
isExpectedFailure bool
|
||||||
volume *core.PersistentVolume
|
volume *core.PersistentVolume
|
||||||
|
disableBlock bool
|
||||||
}{
|
}{
|
||||||
"good-volume": {
|
"good-volume": {
|
||||||
isExpectedFailure: false,
|
isExpectedFailure: false,
|
||||||
|
@ -147,6 +149,22 @@ func TestValidatePersistentVolumes(t *testing.T) {
|
||||||
PersistentVolumeReclaimPolicy: core.PersistentVolumeReclaimRetain,
|
PersistentVolumeReclaimPolicy: core.PersistentVolumeReclaimRetain,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
"good-volume-with-volume-mode": {
|
||||||
|
isExpectedFailure: false,
|
||||||
|
volume: testVolume("foo", "", core.PersistentVolumeSpec{
|
||||||
|
Capacity: core.ResourceList{
|
||||||
|
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
|
||||||
|
},
|
||||||
|
AccessModes: []core.PersistentVolumeAccessMode{core.ReadWriteOnce},
|
||||||
|
PersistentVolumeSource: core.PersistentVolumeSource{
|
||||||
|
HostPath: &core.HostPathVolumeSource{
|
||||||
|
Path: "/foo",
|
||||||
|
Type: newHostPathType(string(core.HostPathDirectory)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
VolumeMode: &validMode,
|
||||||
|
}),
|
||||||
|
},
|
||||||
"invalid-accessmode": {
|
"invalid-accessmode": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
volume: testVolume("foo", "", core.PersistentVolumeSpec{
|
volume: testVolume("foo", "", core.PersistentVolumeSpec{
|
||||||
|
@ -178,6 +196,22 @@ func TestValidatePersistentVolumes(t *testing.T) {
|
||||||
PersistentVolumeReclaimPolicy: "fakeReclaimPolicy",
|
PersistentVolumeReclaimPolicy: "fakeReclaimPolicy",
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
"invalid-volume-mode": {
|
||||||
|
isExpectedFailure: true,
|
||||||
|
volume: testVolume("foo", "", core.PersistentVolumeSpec{
|
||||||
|
Capacity: core.ResourceList{
|
||||||
|
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
|
||||||
|
},
|
||||||
|
AccessModes: []core.PersistentVolumeAccessMode{core.ReadWriteOnce},
|
||||||
|
PersistentVolumeSource: core.PersistentVolumeSource{
|
||||||
|
HostPath: &core.HostPathVolumeSource{
|
||||||
|
Path: "/foo",
|
||||||
|
Type: newHostPathType(string(core.HostPathDirectory)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
VolumeMode: &invalidMode,
|
||||||
|
}),
|
||||||
|
},
|
||||||
"unexpected-namespace": {
|
"unexpected-namespace": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
volume: testVolume("foo", "unexpected-namespace", core.PersistentVolumeSpec{
|
volume: testVolume("foo", "unexpected-namespace", core.PersistentVolumeSpec{
|
||||||
|
@ -336,9 +370,8 @@ func TestValidatePersistentVolumes(t *testing.T) {
|
||||||
StorageClassName: "-invalid-",
|
StorageClassName: "-invalid-",
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
// VolumeMode alpha feature disabled
|
"feature disabled valid volume mode": {
|
||||||
// TODO: remove when no longer alpha
|
disableBlock: true,
|
||||||
"alpha disabled valid volume mode": {
|
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
volume: testVolume("foo", "", core.PersistentVolumeSpec{
|
volume: testVolume("foo", "", core.PersistentVolumeSpec{
|
||||||
Capacity: core.ResourceList{
|
Capacity: core.ResourceList{
|
||||||
|
@ -400,6 +433,8 @@ func TestValidatePersistentVolumes(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, scenario := range scenarios {
|
for name, scenario := range scenarios {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, !scenario.disableBlock)()
|
||||||
errs := ValidatePersistentVolume(scenario.volume)
|
errs := ValidatePersistentVolume(scenario.volume)
|
||||||
if len(errs) == 0 && scenario.isExpectedFailure {
|
if len(errs) == 0 && scenario.isExpectedFailure {
|
||||||
t.Errorf("Unexpected success for scenario: %s", name)
|
t.Errorf("Unexpected success for scenario: %s", name)
|
||||||
|
@ -407,6 +442,7 @@ func TestValidatePersistentVolumes(t *testing.T) {
|
||||||
if len(errs) > 0 && !scenario.isExpectedFailure {
|
if len(errs) > 0 && !scenario.isExpectedFailure {
|
||||||
t.Errorf("Unexpected failure for scenario: %s - %+v", name, errs)
|
t.Errorf("Unexpected failure for scenario: %s - %+v", name, errs)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -791,10 +827,12 @@ func testVolumeClaimStorageClassInAnnotationAndSpec(name, namespace, scNameInAnn
|
||||||
func TestValidatePersistentVolumeClaim(t *testing.T) {
|
func TestValidatePersistentVolumeClaim(t *testing.T) {
|
||||||
invalidClassName := "-invalid-"
|
invalidClassName := "-invalid-"
|
||||||
validClassName := "valid"
|
validClassName := "valid"
|
||||||
|
invalidMode := core.PersistentVolumeMode("fakeVolumeMode")
|
||||||
validMode := core.PersistentVolumeFilesystem
|
validMode := core.PersistentVolumeFilesystem
|
||||||
scenarios := map[string]struct {
|
scenarios := map[string]struct {
|
||||||
isExpectedFailure bool
|
isExpectedFailure bool
|
||||||
claim *core.PersistentVolumeClaim
|
claim *core.PersistentVolumeClaim
|
||||||
|
disableBlock bool
|
||||||
}{
|
}{
|
||||||
"good-claim": {
|
"good-claim": {
|
||||||
isExpectedFailure: false,
|
isExpectedFailure: false,
|
||||||
|
@ -817,6 +855,7 @@ func TestValidatePersistentVolumeClaim(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
StorageClassName: &validClassName,
|
StorageClassName: &validClassName,
|
||||||
|
VolumeMode: &validMode,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
"invalid-claim-zero-capacity": {
|
"invalid-claim-zero-capacity": {
|
||||||
|
@ -988,9 +1027,8 @@ func TestValidatePersistentVolumeClaim(t *testing.T) {
|
||||||
StorageClassName: &invalidClassName,
|
StorageClassName: &invalidClassName,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
// VolumeMode alpha feature disabled
|
"feature disabled valid volume mode": {
|
||||||
// TODO: remove when no longer alpha
|
disableBlock: true,
|
||||||
"disabled alpha valid volume mode": {
|
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
claim: testVolumeClaim("foo", "ns", core.PersistentVolumeClaimSpec{
|
claim: testVolumeClaim("foo", "ns", core.PersistentVolumeClaimSpec{
|
||||||
Selector: &metav1.LabelSelector{
|
Selector: &metav1.LabelSelector{
|
||||||
|
@ -1014,9 +1052,26 @@ func TestValidatePersistentVolumeClaim(t *testing.T) {
|
||||||
VolumeMode: &validMode,
|
VolumeMode: &validMode,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
"invalid-volume-mode": {
|
||||||
|
isExpectedFailure: true,
|
||||||
|
claim: testVolumeClaim("foo", "ns", core.PersistentVolumeClaimSpec{
|
||||||
|
AccessModes: []core.PersistentVolumeAccessMode{
|
||||||
|
core.ReadWriteOnce,
|
||||||
|
core.ReadOnlyMany,
|
||||||
|
},
|
||||||
|
Resources: core.ResourceRequirements{
|
||||||
|
Requests: core.ResourceList{
|
||||||
|
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
VolumeMode: &invalidMode,
|
||||||
|
}),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, scenario := range scenarios {
|
for name, scenario := range scenarios {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, !scenario.disableBlock)()
|
||||||
errs := ValidatePersistentVolumeClaim(scenario.claim)
|
errs := ValidatePersistentVolumeClaim(scenario.claim)
|
||||||
if len(errs) == 0 && scenario.isExpectedFailure {
|
if len(errs) == 0 && scenario.isExpectedFailure {
|
||||||
t.Errorf("Unexpected success for scenario: %s", name)
|
t.Errorf("Unexpected success for scenario: %s", name)
|
||||||
|
@ -1024,6 +1079,7 @@ func TestValidatePersistentVolumeClaim(t *testing.T) {
|
||||||
if len(errs) > 0 && !scenario.isExpectedFailure {
|
if len(errs) > 0 && !scenario.isExpectedFailure {
|
||||||
t.Errorf("Unexpected failure for scenario: %s - %+v", name, errs)
|
t.Errorf("Unexpected failure for scenario: %s - %+v", name, errs)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1106,8 +1162,9 @@ func TestAlphaPVVolumeModeUpdate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, scenario := range scenarios {
|
for name, scenario := range scenarios {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
// ensure we have a resource version specified for updates
|
// ensure we have a resource version specified for updates
|
||||||
toggleBlockVolumeFeature(scenario.enableBlock, t)
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, scenario.enableBlock)()
|
||||||
errs := ValidatePersistentVolumeUpdate(scenario.newPV, scenario.oldPV)
|
errs := ValidatePersistentVolumeUpdate(scenario.newPV, scenario.oldPV)
|
||||||
if len(errs) == 0 && scenario.isExpectedFailure {
|
if len(errs) == 0 && scenario.isExpectedFailure {
|
||||||
t.Errorf("Unexpected success for scenario: %s", name)
|
t.Errorf("Unexpected success for scenario: %s", name)
|
||||||
|
@ -1115,6 +1172,7 @@ func TestAlphaPVVolumeModeUpdate(t *testing.T) {
|
||||||
if len(errs) > 0 && !scenario.isExpectedFailure {
|
if len(errs) > 0 && !scenario.isExpectedFailure {
|
||||||
t.Errorf("Unexpected failure for scenario: %s - %+v", name, errs)
|
t.Errorf("Unexpected failure for scenario: %s - %+v", name, errs)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1558,8 +1616,7 @@ func TestValidatePersistentVolumeClaimUpdate(t *testing.T) {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
// ensure we have a resource version specified for updates
|
// ensure we have a resource version specified for updates
|
||||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExpandPersistentVolumes, scenario.enableResize)()
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExpandPersistentVolumes, scenario.enableResize)()
|
||||||
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, scenario.enableBlock)()
|
||||||
toggleBlockVolumeFeature(scenario.enableBlock, t)
|
|
||||||
scenario.oldClaim.ResourceVersion = "1"
|
scenario.oldClaim.ResourceVersion = "1"
|
||||||
scenario.newClaim.ResourceVersion = "1"
|
scenario.newClaim.ResourceVersion = "1"
|
||||||
errs := ValidatePersistentVolumeClaimUpdate(scenario.newClaim, scenario.oldClaim)
|
errs := ValidatePersistentVolumeClaimUpdate(scenario.newClaim, scenario.oldClaim)
|
||||||
|
@ -1573,23 +1630,6 @@ func TestValidatePersistentVolumeClaimUpdate(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func toggleBlockVolumeFeature(toggleFlag bool, t *testing.T) {
|
|
||||||
if toggleFlag {
|
|
||||||
// Enable alpha feature BlockVolume
|
|
||||||
err := utilfeature.DefaultFeatureGate.Set("BlockVolume=true")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to enable feature gate for BlockVolume: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err := utilfeature.DefaultFeatureGate.Set("BlockVolume=false")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to disable feature gate for BlockVolume: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValidateKeyToPath(t *testing.T) {
|
func TestValidateKeyToPath(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
kp core.KeyToPath
|
kp core.KeyToPath
|
||||||
|
@ -3880,13 +3920,9 @@ func TestAlphaHugePagesIsolation(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAlphaPVCVolumeMode(t *testing.T) {
|
func TestPVCVolumeMode(t *testing.T) {
|
||||||
// Enable alpha feature BlockVolume for PVC
|
// Enable feature BlockVolume for PVC
|
||||||
err := utilfeature.DefaultFeatureGate.Set("BlockVolume=true")
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to enable feature gate for BlockVolume: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
block := core.PersistentVolumeBlock
|
block := core.PersistentVolumeBlock
|
||||||
file := core.PersistentVolumeFilesystem
|
file := core.PersistentVolumeFilesystem
|
||||||
|
@ -3917,13 +3953,9 @@ func TestAlphaPVCVolumeMode(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAlphaPVVolumeMode(t *testing.T) {
|
func TestPVVolumeMode(t *testing.T) {
|
||||||
// Enable alpha feature BlockVolume for PV
|
// Enable feature BlockVolume for PVC
|
||||||
err := utilfeature.DefaultFeatureGate.Set("BlockVolume=true")
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to enable feature gate for BlockVolume: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
block := core.PersistentVolumeBlock
|
block := core.PersistentVolumeBlock
|
||||||
file := core.PersistentVolumeFilesystem
|
file := core.PersistentVolumeFilesystem
|
||||||
|
@ -5088,12 +5120,8 @@ func TestAlphaValidateVolumeDevices(t *testing.T) {
|
||||||
{Name: "abc-123", MountPath: "/this/path/exists"},
|
{Name: "abc-123", MountPath: "/this/path/exists"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// enable Alpha BlockVolume
|
// enable BlockVolume
|
||||||
err1 := utilfeature.DefaultFeatureGate.Set("BlockVolume=true")
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||||
if err1 != nil {
|
|
||||||
t.Errorf("Failed to enable feature gate for BlockVolume: %v", err1)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Success Cases:
|
// Success Cases:
|
||||||
// Validate normal success cases - only PVC volumeSource
|
// Validate normal success cases - only PVC volumeSource
|
||||||
if errs := ValidateVolumeDevices(successCase, GetVolumeMountMap(goodVolumeMounts), vols, field.NewPath("field")); len(errs) != 0 {
|
if errs := ValidateVolumeDevices(successCase, GetVolumeMountMap(goodVolumeMounts), vols, field.NewPath("field")); len(errs) != 0 {
|
||||||
|
@ -5108,12 +5136,8 @@ func TestAlphaValidateVolumeDevices(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable Alpha BlockVolume
|
// disable BlockVolume
|
||||||
err2 := utilfeature.DefaultFeatureGate.Set("BlockVolume=false")
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)()
|
||||||
if err2 != nil {
|
|
||||||
t.Errorf("Failed to disable feature gate for BlockVolume: %v", err2)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if errs := ValidateVolumeDevices(disabledAlphaVolDevice, GetVolumeMountMap(goodVolumeMounts), vols, field.NewPath("field")); len(errs) == 0 {
|
if errs := ValidateVolumeDevices(disabledAlphaVolDevice, GetVolumeMountMap(goodVolumeMounts), vols, field.NewPath("field")); len(errs) == 0 {
|
||||||
t.Errorf("expected failure: %v", errs)
|
t.Errorf("expected failure: %v", errs)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ import (
|
||||||
storage "k8s.io/api/storage/v1"
|
storage "k8s.io/api/storage/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
|
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Test single call to syncClaim and syncVolume methods.
|
// Test single call to syncClaim and syncVolume methods.
|
||||||
|
@ -35,8 +37,6 @@ func TestSync(t *testing.T) {
|
||||||
"foo": "true",
|
"foo": "true",
|
||||||
"bar": "false",
|
"bar": "false",
|
||||||
}
|
}
|
||||||
modeBlock := v1.PersistentVolumeBlock
|
|
||||||
modeFile := v1.PersistentVolumeFilesystem
|
|
||||||
|
|
||||||
tests := []controllerTest{
|
tests := []controllerTest{
|
||||||
// [Unit test set 1] User did not care which PV they get.
|
// [Unit test set 1] User did not care which PV they get.
|
||||||
|
@ -589,9 +589,22 @@ func TestSync(t *testing.T) {
|
||||||
newClaimArray("claim13-5", "uid13-5", "1Gi", "volume13-5", v1.ClaimBound, nil, annBoundByController, annBindCompleted),
|
newClaimArray("claim13-5", "uid13-5", "1Gi", "volume13-5", v1.ClaimBound, nil, annBoundByController, annBindCompleted),
|
||||||
noevents, noerrors, testSyncClaim,
|
noevents, noerrors, testSyncClaim,
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
runSyncTests(t, tests, []*storage.StorageClass{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: classWait},
|
||||||
|
VolumeBindingMode: &modeWait,
|
||||||
|
},
|
||||||
|
}, []*v1.Pod{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncBlockVolumeDisabled(t *testing.T) {
|
||||||
|
modeBlock := v1.PersistentVolumeBlock
|
||||||
|
modeFile := v1.PersistentVolumeFilesystem
|
||||||
// All of these should bind as feature set is not enabled for BlockVolume
|
// All of these should bind as feature set is not enabled for BlockVolume
|
||||||
// meaning volumeMode will be ignored and dropped
|
// meaning volumeMode will be ignored and dropped
|
||||||
|
tests := []controllerTest{
|
||||||
{
|
{
|
||||||
// syncVolume binds a requested block claim to a block volume
|
// syncVolume binds a requested block claim to a block volume
|
||||||
"14-1 - binding to volumeMode block",
|
"14-1 - binding to volumeMode block",
|
||||||
|
@ -639,6 +652,7 @@ func TestSync(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)()
|
||||||
runSyncTests(t, tests, []*storage.StorageClass{
|
runSyncTests(t, tests, []*storage.StorageClass{
|
||||||
{
|
{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: classWait},
|
ObjectMeta: metav1.ObjectMeta{Name: classWait},
|
||||||
|
@ -647,7 +661,7 @@ func TestSync(t *testing.T) {
|
||||||
}, []*v1.Pod{})
|
}, []*v1.Pod{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSyncAlphaBlockVolume(t *testing.T) {
|
func TestSyncBlockVolume(t *testing.T) {
|
||||||
modeBlock := v1.PersistentVolumeBlock
|
modeBlock := v1.PersistentVolumeBlock
|
||||||
modeFile := v1.PersistentVolumeFilesystem
|
modeFile := v1.PersistentVolumeFilesystem
|
||||||
|
|
||||||
|
@ -827,12 +841,7 @@ func TestSyncAlphaBlockVolume(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := utilfeature.DefaultFeatureGate.Set("BlockVolume=true")
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to enable feature gate for BlockVolume: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer utilfeature.DefaultFeatureGate.Set("BlockVolume=false")
|
|
||||||
|
|
||||||
runSyncTests(t, tests, []*storage.StorageClass{}, []*v1.Pod{})
|
runSyncTests(t, tests, []*storage.StorageClass{}, []*v1.Pod{})
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/util/diff"
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
|
@ -48,6 +49,7 @@ import (
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
vol "k8s.io/kubernetes/pkg/volume"
|
vol "k8s.io/kubernetes/pkg/volume"
|
||||||
"k8s.io/kubernetes/pkg/volume/util/recyclerclient"
|
"k8s.io/kubernetes/pkg/volume/util/recyclerclient"
|
||||||
)
|
)
|
||||||
|
@ -179,6 +181,12 @@ func (r *volumeReactor) React(action core.Action) (handled bool, ret runtime.Obj
|
||||||
return true, nil, fmt.Errorf("Cannot create volume %s: volume already exists", volume.Name)
|
return true, nil, fmt.Errorf("Cannot create volume %s: volume already exists", volume.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mimic apiserver defaulting
|
||||||
|
if volume.Spec.VolumeMode == nil && utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||||
|
volume.Spec.VolumeMode = new(v1.PersistentVolumeMode)
|
||||||
|
*volume.Spec.VolumeMode = v1.PersistentVolumeFilesystem
|
||||||
|
}
|
||||||
|
|
||||||
// Store the updated object to appropriate places.
|
// Store the updated object to appropriate places.
|
||||||
r.volumes[volume.Name] = volume
|
r.volumes[volume.Name] = volume
|
||||||
r.changedObjects = append(r.changedObjects, volume)
|
r.changedObjects = append(r.changedObjects, volume)
|
||||||
|
@ -630,6 +638,7 @@ func newTestController(kubeClient clientset.Interface, informerFactory informers
|
||||||
|
|
||||||
// newVolume returns a new volume with given attributes
|
// newVolume returns a new volume with given attributes
|
||||||
func newVolume(name, capacity, boundToClaimUID, boundToClaimName string, phase v1.PersistentVolumePhase, reclaimPolicy v1.PersistentVolumeReclaimPolicy, class string, annotations ...string) *v1.PersistentVolume {
|
func newVolume(name, capacity, boundToClaimUID, boundToClaimName string, phase v1.PersistentVolumePhase, reclaimPolicy v1.PersistentVolumeReclaimPolicy, class string, annotations ...string) *v1.PersistentVolume {
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
volume := v1.PersistentVolume{
|
volume := v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
@ -645,6 +654,7 @@ func newVolume(name, capacity, boundToClaimUID, boundToClaimName string, phase v
|
||||||
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce, v1.ReadOnlyMany},
|
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce, v1.ReadOnlyMany},
|
||||||
PersistentVolumeReclaimPolicy: reclaimPolicy,
|
PersistentVolumeReclaimPolicy: reclaimPolicy,
|
||||||
StorageClassName: class,
|
StorageClassName: class,
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: phase,
|
Phase: phase,
|
||||||
|
@ -740,6 +750,7 @@ func newVolumeArray(name, capacity, boundToClaimUID, boundToClaimName string, ph
|
||||||
|
|
||||||
// newClaim returns a new claim with given attributes
|
// newClaim returns a new claim with given attributes
|
||||||
func newClaim(name, claimUID, capacity, boundToVolume string, phase v1.PersistentVolumeClaimPhase, class *string, annotations ...string) *v1.PersistentVolumeClaim {
|
func newClaim(name, claimUID, capacity, boundToVolume string, phase v1.PersistentVolumeClaimPhase, class *string, annotations ...string) *v1.PersistentVolumeClaim {
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
claim := v1.PersistentVolumeClaim{
|
claim := v1.PersistentVolumeClaim{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
@ -756,6 +767,7 @@ func newClaim(name, claimUID, capacity, boundToVolume string, phase v1.Persisten
|
||||||
},
|
},
|
||||||
VolumeName: boundToVolume,
|
VolumeName: boundToVolume,
|
||||||
StorageClassName: class,
|
StorageClassName: class,
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeClaimStatus{
|
Status: v1.PersistentVolumeClaimStatus{
|
||||||
Phase: phase,
|
Phase: phase,
|
||||||
|
@ -1226,6 +1238,7 @@ func (plugin *mockVolumePlugin) Provision(selectedNode *v1.Node, allowedTopologi
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
pv.Spec.VolumeMode = plugin.provisionOptions.PVC.Spec.VolumeMode
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.provisionCallCounter++
|
plugin.provisionCallCounter++
|
||||||
|
|
|
@ -158,13 +158,13 @@ func findMatchingVolume(
|
||||||
|
|
||||||
volumeQty := volume.Spec.Capacity[v1.ResourceStorage]
|
volumeQty := volume.Spec.Capacity[v1.ResourceStorage]
|
||||||
|
|
||||||
// check if volumeModes do not match (Alpha and feature gate protected)
|
// check if volumeModes do not match (feature gate protected)
|
||||||
isMisMatch, err := checkVolumeModeMisMatches(&claim.Spec, &volume.Spec)
|
isMismatch, err := checkVolumeModeMismatches(&claim.Spec, &volume.Spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error checking if volumeMode was a mismatch: %v", err)
|
return nil, fmt.Errorf("error checking if volumeMode was a mismatch: %v", err)
|
||||||
}
|
}
|
||||||
// filter out mismatching volumeModes
|
// filter out mismatching volumeModes
|
||||||
if isMisMatch {
|
if isMismatch {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,25 +258,24 @@ func findMatchingVolume(
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkVolumeModeMatches is a convenience method that checks volumeMode for PersistentVolume
|
// checkVolumeModeMismatches is a convenience method that checks volumeMode for PersistentVolume
|
||||||
// and PersistentVolumeClaims along with making sure that the Alpha feature gate BlockVolume is
|
// and PersistentVolumeClaims
|
||||||
// enabled.
|
func checkVolumeModeMismatches(pvcSpec *v1.PersistentVolumeClaimSpec, pvSpec *v1.PersistentVolumeSpec) (bool, error) {
|
||||||
// This is Alpha and could change in the future.
|
if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||||
func checkVolumeModeMisMatches(pvcSpec *v1.PersistentVolumeClaimSpec, pvSpec *v1.PersistentVolumeSpec) (bool, error) {
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
|
||||||
if pvSpec.VolumeMode != nil && pvcSpec.VolumeMode != nil {
|
|
||||||
requestedVolumeMode := *pvcSpec.VolumeMode
|
|
||||||
pvVolumeMode := *pvSpec.VolumeMode
|
|
||||||
return requestedVolumeMode != pvVolumeMode, nil
|
|
||||||
} else {
|
|
||||||
// This also should retrun an error, this means that
|
|
||||||
// the defaulting has failed.
|
|
||||||
return true, fmt.Errorf("api defaulting for volumeMode failed")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// feature gate is disabled
|
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In HA upgrades, we cannot guarantee that the apiserver is on a version >= controller-manager.
|
||||||
|
// So we default a nil volumeMode to filesystem
|
||||||
|
requestedVolumeMode := v1.PersistentVolumeFilesystem
|
||||||
|
if pvcSpec.VolumeMode != nil {
|
||||||
|
requestedVolumeMode = *pvcSpec.VolumeMode
|
||||||
|
}
|
||||||
|
pvVolumeMode := v1.PersistentVolumeFilesystem
|
||||||
|
if pvSpec.VolumeMode != nil {
|
||||||
|
pvVolumeMode = *pvSpec.VolumeMode
|
||||||
|
}
|
||||||
|
return requestedVolumeMode != pvVolumeMode, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// findBestMatchForClaim is a convenience method that finds a volume by the claim's AccessModes and requests for Storage
|
// findBestMatchForClaim is a convenience method that finds a volume by the claim's AccessModes and requests for Storage
|
||||||
|
|
|
@ -33,6 +33,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func makePVC(size string, modfn func(*v1.PersistentVolumeClaim)) *v1.PersistentVolumeClaim {
|
func makePVC(size string, modfn func(*v1.PersistentVolumeClaim)) *v1.PersistentVolumeClaim {
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
pvc := v1.PersistentVolumeClaim{
|
pvc := v1.PersistentVolumeClaim{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "claim01",
|
Name: "claim01",
|
||||||
|
@ -45,6 +46,7 @@ func makePVC(size string, modfn func(*v1.PersistentVolumeClaim)) *v1.PersistentV
|
||||||
v1.ResourceName(v1.ResourceStorage): resource.MustParse(size),
|
v1.ResourceName(v1.ResourceStorage): resource.MustParse(size),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if modfn != nil {
|
if modfn != nil {
|
||||||
|
@ -197,6 +199,7 @@ func TestMatchVolume(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMatchingWithBoundVolumes(t *testing.T) {
|
func TestMatchingWithBoundVolumes(t *testing.T) {
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
volumeIndex := newPersistentVolumeOrderedIndex()
|
volumeIndex := newPersistentVolumeOrderedIndex()
|
||||||
// two similar volumes, one is bound
|
// two similar volumes, one is bound
|
||||||
pv1 := &v1.PersistentVolume{
|
pv1 := &v1.PersistentVolume{
|
||||||
|
@ -214,6 +217,7 @@ func TestMatchingWithBoundVolumes(t *testing.T) {
|
||||||
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce, v1.ReadOnlyMany},
|
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce, v1.ReadOnlyMany},
|
||||||
// this one we're pretending is already bound
|
// this one we're pretending is already bound
|
||||||
ClaimRef: &v1.ObjectReference{UID: "abc123"},
|
ClaimRef: &v1.ObjectReference{UID: "abc123"},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeBound,
|
Phase: v1.VolumeBound,
|
||||||
|
@ -233,6 +237,7 @@ func TestMatchingWithBoundVolumes(t *testing.T) {
|
||||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{},
|
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{},
|
||||||
},
|
},
|
||||||
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce, v1.ReadOnlyMany},
|
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce, v1.ReadOnlyMany},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -254,6 +259,7 @@ func TestMatchingWithBoundVolumes(t *testing.T) {
|
||||||
v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G"),
|
v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,6 +334,7 @@ func TestAllPossibleAccessModes(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
|
func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
gce := &v1.PersistentVolume{
|
gce := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{UID: "001", Name: "gce"},
|
ObjectMeta: metav1.ObjectMeta{UID: "001", Name: "gce"},
|
||||||
Spec: v1.PersistentVolumeSpec{
|
Spec: v1.PersistentVolumeSpec{
|
||||||
|
@ -337,6 +344,7 @@ func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
|
||||||
v1.ReadWriteOnce,
|
v1.ReadWriteOnce,
|
||||||
v1.ReadOnlyMany,
|
v1.ReadOnlyMany,
|
||||||
},
|
},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -351,6 +359,7 @@ func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
|
||||||
AccessModes: []v1.PersistentVolumeAccessMode{
|
AccessModes: []v1.PersistentVolumeAccessMode{
|
||||||
v1.ReadWriteOnce,
|
v1.ReadWriteOnce,
|
||||||
},
|
},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -367,6 +376,7 @@ func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
|
||||||
v1.ReadOnlyMany,
|
v1.ReadOnlyMany,
|
||||||
v1.ReadWriteMany,
|
v1.ReadWriteMany,
|
||||||
},
|
},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -381,6 +391,7 @@ func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
|
||||||
Spec: v1.PersistentVolumeClaimSpec{
|
Spec: v1.PersistentVolumeClaimSpec{
|
||||||
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
|
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
|
||||||
Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G")}},
|
Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G")}},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,6 +451,7 @@ func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestVolumes() []*v1.PersistentVolume {
|
func createTestVolumes() []*v1.PersistentVolume {
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
// these volumes are deliberately out-of-order to test indexing and sorting
|
// these volumes are deliberately out-of-order to test indexing and sorting
|
||||||
return []*v1.PersistentVolume{
|
return []*v1.PersistentVolume{
|
||||||
{
|
{
|
||||||
|
@ -458,6 +470,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
v1.ReadWriteOnce,
|
v1.ReadWriteOnce,
|
||||||
v1.ReadOnlyMany,
|
v1.ReadOnlyMany,
|
||||||
},
|
},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -481,6 +494,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
},
|
},
|
||||||
// this one we're pretending is already bound
|
// this one we're pretending is already bound
|
||||||
ClaimRef: &v1.ObjectReference{UID: "def456"},
|
ClaimRef: &v1.ObjectReference{UID: "def456"},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeBound,
|
Phase: v1.VolumeBound,
|
||||||
|
@ -503,6 +517,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
v1.ReadOnlyMany,
|
v1.ReadOnlyMany,
|
||||||
v1.ReadWriteMany,
|
v1.ReadWriteMany,
|
||||||
},
|
},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -526,6 +541,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
},
|
},
|
||||||
// this one we're pretending is already bound
|
// this one we're pretending is already bound
|
||||||
ClaimRef: &v1.ObjectReference{UID: "abc123"},
|
ClaimRef: &v1.ObjectReference{UID: "abc123"},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeBound,
|
Phase: v1.VolumeBound,
|
||||||
|
@ -548,6 +564,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
v1.ReadOnlyMany,
|
v1.ReadOnlyMany,
|
||||||
v1.ReadWriteMany,
|
v1.ReadWriteMany,
|
||||||
},
|
},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -569,6 +586,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
v1.ReadWriteOnce,
|
v1.ReadWriteOnce,
|
||||||
v1.ReadOnlyMany,
|
v1.ReadOnlyMany,
|
||||||
},
|
},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -591,6 +609,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
v1.ReadOnlyMany,
|
v1.ReadOnlyMany,
|
||||||
v1.ReadWriteMany,
|
v1.ReadWriteMany,
|
||||||
},
|
},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -614,6 +633,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
AccessModes: []v1.PersistentVolumeAccessMode{
|
AccessModes: []v1.PersistentVolumeAccessMode{
|
||||||
v1.ReadWriteOnce,
|
v1.ReadWriteOnce,
|
||||||
},
|
},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -638,6 +658,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
v1.ReadWriteOnce,
|
v1.ReadWriteOnce,
|
||||||
},
|
},
|
||||||
StorageClassName: classSilver,
|
StorageClassName: classSilver,
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -659,6 +680,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
v1.ReadWriteOnce,
|
v1.ReadWriteOnce,
|
||||||
},
|
},
|
||||||
StorageClassName: classSilver,
|
StorageClassName: classSilver,
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -680,6 +702,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
v1.ReadWriteOnce,
|
v1.ReadWriteOnce,
|
||||||
},
|
},
|
||||||
StorageClassName: classGold,
|
StorageClassName: classGold,
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -703,6 +726,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
v1.ReadWriteMany,
|
v1.ReadWriteMany,
|
||||||
},
|
},
|
||||||
StorageClassName: classLarge,
|
StorageClassName: classLarge,
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -726,6 +750,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
v1.ReadWriteMany,
|
v1.ReadWriteMany,
|
||||||
},
|
},
|
||||||
StorageClassName: classLarge,
|
StorageClassName: classLarge,
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -749,6 +774,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
},
|
},
|
||||||
StorageClassName: classWait,
|
StorageClassName: classWait,
|
||||||
NodeAffinity: getVolumeNodeAffinity("key1", "value1"),
|
NodeAffinity: getVolumeNodeAffinity("key1", "value1"),
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -772,6 +798,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
},
|
},
|
||||||
StorageClassName: classWait,
|
StorageClassName: classWait,
|
||||||
NodeAffinity: getVolumeNodeAffinity("key1", "value1"),
|
NodeAffinity: getVolumeNodeAffinity("key1", "value1"),
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -796,6 +823,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
StorageClassName: classWait,
|
StorageClassName: classWait,
|
||||||
ClaimRef: &v1.ObjectReference{Name: "claim02", Namespace: "myns"},
|
ClaimRef: &v1.ObjectReference{Name: "claim02", Namespace: "myns"},
|
||||||
NodeAffinity: getVolumeNodeAffinity("key1", "value1"),
|
NodeAffinity: getVolumeNodeAffinity("key1", "value1"),
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -819,6 +847,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
},
|
},
|
||||||
StorageClassName: classWait,
|
StorageClassName: classWait,
|
||||||
NodeAffinity: getVolumeNodeAffinity("key1", "value3"),
|
NodeAffinity: getVolumeNodeAffinity("key1", "value3"),
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -842,6 +871,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
},
|
},
|
||||||
StorageClassName: classWait,
|
StorageClassName: classWait,
|
||||||
NodeAffinity: getVolumeNodeAffinity("key1", "value4"),
|
NodeAffinity: getVolumeNodeAffinity("key1", "value4"),
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumePending,
|
Phase: v1.VolumePending,
|
||||||
|
@ -865,6 +895,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
},
|
},
|
||||||
StorageClassName: classWait,
|
StorageClassName: classWait,
|
||||||
NodeAffinity: getVolumeNodeAffinity("key1", "value4"),
|
NodeAffinity: getVolumeNodeAffinity("key1", "value4"),
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeFailed,
|
Phase: v1.VolumeFailed,
|
||||||
|
@ -888,6 +919,7 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
},
|
},
|
||||||
StorageClassName: classWait,
|
StorageClassName: classWait,
|
||||||
NodeAffinity: getVolumeNodeAffinity("key1", "value4"),
|
NodeAffinity: getVolumeNodeAffinity("key1", "value4"),
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeReleased,
|
Phase: v1.VolumeReleased,
|
||||||
|
@ -911,12 +943,14 @@ func createTestVolumes() []*v1.PersistentVolume {
|
||||||
},
|
},
|
||||||
StorageClassName: classWait,
|
StorageClassName: classWait,
|
||||||
NodeAffinity: getVolumeNodeAffinity("key1", "value4"),
|
NodeAffinity: getVolumeNodeAffinity("key1", "value4"),
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testVolume(name, size string) *v1.PersistentVolume {
|
func testVolume(name, size string) *v1.PersistentVolume {
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
return &v1.PersistentVolume{
|
return &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
@ -926,6 +960,7 @@ func testVolume(name, size string) *v1.PersistentVolume {
|
||||||
Capacity: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse(size)},
|
Capacity: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse(size)},
|
||||||
PersistentVolumeSource: v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{}},
|
PersistentVolumeSource: v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{}},
|
||||||
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
|
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -1003,34 +1038,36 @@ func createVolumeModeFilesystemTestVolume() *v1.PersistentVolume {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createVolumeModeNilTestVolume() *v1.PersistentVolume {
|
||||||
|
return &v1.PersistentVolume{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
UID: "local-1",
|
||||||
|
Name: "nil-mode",
|
||||||
|
},
|
||||||
|
Spec: v1.PersistentVolumeSpec{
|
||||||
|
Capacity: v1.ResourceList{
|
||||||
|
v1.ResourceName(v1.ResourceStorage): resource.MustParse("10G"),
|
||||||
|
},
|
||||||
|
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||||
|
Local: &v1.LocalVolumeSource{},
|
||||||
|
},
|
||||||
|
AccessModes: []v1.PersistentVolumeAccessMode{
|
||||||
|
v1.ReadWriteOnce,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Status: v1.PersistentVolumeStatus{
|
||||||
|
Phase: v1.VolumeAvailable,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func createTestVolOrderedIndex(pv *v1.PersistentVolume) persistentVolumeOrderedIndex {
|
func createTestVolOrderedIndex(pv *v1.PersistentVolume) persistentVolumeOrderedIndex {
|
||||||
volFile := newPersistentVolumeOrderedIndex()
|
volFile := newPersistentVolumeOrderedIndex()
|
||||||
volFile.store.Add(pv)
|
volFile.store.Add(pv)
|
||||||
return volFile
|
return volFile
|
||||||
}
|
}
|
||||||
|
|
||||||
func toggleFeature(toggleFlag bool, featureName string, t *testing.T) {
|
func TestVolumeModeCheck(t *testing.T) {
|
||||||
var valueStr string
|
|
||||||
if toggleFlag {
|
|
||||||
// Enable feature
|
|
||||||
valueStr = featureName + "=true"
|
|
||||||
err := utilfeature.DefaultFeatureGate.Set(valueStr)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to enable feature gate for %s: %v", featureName, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Disable feature
|
|
||||||
valueStr = featureName + "=false"
|
|
||||||
err := utilfeature.DefaultFeatureGate.Set(valueStr)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to disable feature gate for %s: %v", featureName, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAlphaVolumeModeCheck(t *testing.T) {
|
|
||||||
|
|
||||||
blockMode := v1.PersistentVolumeBlock
|
blockMode := v1.PersistentVolumeBlock
|
||||||
filesystemMode := v1.PersistentVolumeFilesystem
|
filesystemMode := v1.PersistentVolumeFilesystem
|
||||||
|
@ -1038,55 +1075,85 @@ func TestAlphaVolumeModeCheck(t *testing.T) {
|
||||||
// If feature gate is enabled, VolumeMode will always be defaulted
|
// If feature gate is enabled, VolumeMode will always be defaulted
|
||||||
// If feature gate is disabled, VolumeMode is dropped by API and ignored
|
// If feature gate is disabled, VolumeMode is dropped by API and ignored
|
||||||
scenarios := map[string]struct {
|
scenarios := map[string]struct {
|
||||||
isExpectedMisMatch bool
|
isExpectedMismatch bool
|
||||||
vol *v1.PersistentVolume
|
vol *v1.PersistentVolume
|
||||||
pvc *v1.PersistentVolumeClaim
|
pvc *v1.PersistentVolumeClaim
|
||||||
enableBlock bool
|
enableBlock bool
|
||||||
}{
|
}{
|
||||||
"feature enabled - pvc block and pv filesystem": {
|
"feature enabled - pvc block and pv filesystem": {
|
||||||
isExpectedMisMatch: true,
|
isExpectedMismatch: true,
|
||||||
vol: createVolumeModeFilesystemTestVolume(),
|
vol: createVolumeModeFilesystemTestVolume(),
|
||||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||||
enableBlock: true,
|
enableBlock: true,
|
||||||
},
|
},
|
||||||
"feature enabled - pvc filesystem and pv block": {
|
"feature enabled - pvc filesystem and pv block": {
|
||||||
isExpectedMisMatch: true,
|
isExpectedMismatch: true,
|
||||||
vol: createVolumeModeBlockTestVolume(),
|
vol: createVolumeModeBlockTestVolume(),
|
||||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||||
enableBlock: true,
|
enableBlock: true,
|
||||||
},
|
},
|
||||||
"feature enabled - pvc block and pv block": {
|
"feature enabled - pvc block and pv block": {
|
||||||
isExpectedMisMatch: false,
|
isExpectedMismatch: false,
|
||||||
vol: createVolumeModeBlockTestVolume(),
|
vol: createVolumeModeBlockTestVolume(),
|
||||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||||
enableBlock: true,
|
enableBlock: true,
|
||||||
},
|
},
|
||||||
"feature enabled - pvc filesystem and pv filesystem": {
|
"feature enabled - pvc filesystem and pv filesystem": {
|
||||||
isExpectedMisMatch: false,
|
isExpectedMismatch: false,
|
||||||
vol: createVolumeModeFilesystemTestVolume(),
|
vol: createVolumeModeFilesystemTestVolume(),
|
||||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||||
enableBlock: true,
|
enableBlock: true,
|
||||||
},
|
},
|
||||||
|
"feature enabled - pvc filesystem and pv nil": {
|
||||||
|
isExpectedMismatch: false,
|
||||||
|
vol: createVolumeModeNilTestVolume(),
|
||||||
|
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||||
|
enableBlock: true,
|
||||||
|
},
|
||||||
|
"feature enabled - pvc nil and pv filesytem": {
|
||||||
|
isExpectedMismatch: false,
|
||||||
|
vol: createVolumeModeFilesystemTestVolume(),
|
||||||
|
pvc: makeVolumeModePVC("8G", nil, nil),
|
||||||
|
enableBlock: true,
|
||||||
|
},
|
||||||
|
"feature enabled - pvc nil and pv nil": {
|
||||||
|
isExpectedMismatch: false,
|
||||||
|
vol: createVolumeModeNilTestVolume(),
|
||||||
|
pvc: makeVolumeModePVC("8G", nil, nil),
|
||||||
|
enableBlock: true,
|
||||||
|
},
|
||||||
|
"feature enabled - pvc nil and pv block": {
|
||||||
|
isExpectedMismatch: true,
|
||||||
|
vol: createVolumeModeBlockTestVolume(),
|
||||||
|
pvc: makeVolumeModePVC("8G", nil, nil),
|
||||||
|
enableBlock: true,
|
||||||
|
},
|
||||||
|
"feature enabled - pvc block and pv nil": {
|
||||||
|
isExpectedMismatch: true,
|
||||||
|
vol: createVolumeModeNilTestVolume(),
|
||||||
|
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||||
|
enableBlock: true,
|
||||||
|
},
|
||||||
"feature disabled - pvc block and pv filesystem": {
|
"feature disabled - pvc block and pv filesystem": {
|
||||||
isExpectedMisMatch: false,
|
isExpectedMismatch: false,
|
||||||
vol: createVolumeModeFilesystemTestVolume(),
|
vol: createVolumeModeFilesystemTestVolume(),
|
||||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||||
enableBlock: false,
|
enableBlock: false,
|
||||||
},
|
},
|
||||||
"feature disabled - pvc filesystem and pv block": {
|
"feature disabled - pvc filesystem and pv block": {
|
||||||
isExpectedMisMatch: false,
|
isExpectedMismatch: false,
|
||||||
vol: createVolumeModeBlockTestVolume(),
|
vol: createVolumeModeBlockTestVolume(),
|
||||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||||
enableBlock: false,
|
enableBlock: false,
|
||||||
},
|
},
|
||||||
"feature disabled - pvc block and pv block": {
|
"feature disabled - pvc block and pv block": {
|
||||||
isExpectedMisMatch: false,
|
isExpectedMismatch: false,
|
||||||
vol: createVolumeModeBlockTestVolume(),
|
vol: createVolumeModeBlockTestVolume(),
|
||||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||||
enableBlock: false,
|
enableBlock: false,
|
||||||
},
|
},
|
||||||
"feature disabled - pvc filesystem and pv filesystem": {
|
"feature disabled - pvc filesystem and pv filesystem": {
|
||||||
isExpectedMisMatch: false,
|
isExpectedMismatch: false,
|
||||||
vol: createVolumeModeFilesystemTestVolume(),
|
vol: createVolumeModeFilesystemTestVolume(),
|
||||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||||
enableBlock: false,
|
enableBlock: false,
|
||||||
|
@ -1094,25 +1161,23 @@ func TestAlphaVolumeModeCheck(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, scenario := range scenarios {
|
for name, scenario := range scenarios {
|
||||||
toggleFeature(scenario.enableBlock, "BlockVolume", t)
|
recover := utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, scenario.enableBlock)
|
||||||
expectedMisMatch, err := checkVolumeModeMisMatches(&scenario.pvc.Spec, &scenario.vol.Spec)
|
expectedMismatch, err := checkVolumeModeMismatches(&scenario.pvc.Spec, &scenario.vol.Spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Unexpected failure for checkVolumeModeMisMatches: %v", err)
|
t.Errorf("Unexpected failure for checkVolumeModeMismatches: %v", err)
|
||||||
}
|
}
|
||||||
// expected to match but either got an error or no returned pvmatch
|
// expected to match but either got an error or no returned pvmatch
|
||||||
if expectedMisMatch && !scenario.isExpectedMisMatch {
|
if expectedMismatch && !scenario.isExpectedMismatch {
|
||||||
t.Errorf("Unexpected failure for scenario, expected not to mismatch on modes but did: %s", name)
|
t.Errorf("Unexpected failure for scenario, expected not to mismatch on modes but did: %s", name)
|
||||||
}
|
}
|
||||||
if !expectedMisMatch && scenario.isExpectedMisMatch {
|
if !expectedMismatch && scenario.isExpectedMismatch {
|
||||||
t.Errorf("Unexpected failure for scenario, did not mismatch on mode when expected to mismatch: %s", name)
|
t.Errorf("Unexpected failure for scenario, did not mismatch on mode when expected to mismatch: %s", name)
|
||||||
}
|
}
|
||||||
|
recover()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure feature gate is turned off
|
func TestFilteringVolumeModes(t *testing.T) {
|
||||||
toggleFeature(false, "BlockVolume", t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAlphaFilteringVolumeModes(t *testing.T) {
|
|
||||||
blockMode := v1.PersistentVolumeBlock
|
blockMode := v1.PersistentVolumeBlock
|
||||||
filesystemMode := v1.PersistentVolumeFilesystem
|
filesystemMode := v1.PersistentVolumeFilesystem
|
||||||
|
|
||||||
|
@ -1187,7 +1252,7 @@ func TestAlphaFilteringVolumeModes(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, scenario := range scenarios {
|
for name, scenario := range scenarios {
|
||||||
toggleFeature(scenario.enableBlock, "BlockVolume", t)
|
recover := utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, scenario.enableBlock)
|
||||||
pvmatch, err := scenario.vol.findBestMatchForClaim(scenario.pvc, false)
|
pvmatch, err := scenario.vol.findBestMatchForClaim(scenario.pvc, false)
|
||||||
// expected to match but either got an error or no returned pvmatch
|
// expected to match but either got an error or no returned pvmatch
|
||||||
if pvmatch == nil && scenario.isExpectedMatch {
|
if pvmatch == nil && scenario.isExpectedMatch {
|
||||||
|
@ -1203,13 +1268,12 @@ func TestAlphaFilteringVolumeModes(t *testing.T) {
|
||||||
if err != nil && !scenario.isExpectedMatch {
|
if err != nil && !scenario.isExpectedMatch {
|
||||||
t.Errorf("Unexpected failure for scenario: %s - %+v", name, err)
|
t.Errorf("Unexpected failure for scenario: %s - %+v", name, err)
|
||||||
}
|
}
|
||||||
|
recover()
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure feature gate is turned off
|
|
||||||
toggleFeature(false, "BlockVolume", t)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStorageObjectInUseProtectionFiltering(t *testing.T) {
|
func TestStorageObjectInUseProtectionFiltering(t *testing.T) {
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "pv1",
|
Name: "pv1",
|
||||||
|
@ -1219,6 +1283,7 @@ func TestStorageObjectInUseProtectionFiltering(t *testing.T) {
|
||||||
Capacity: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G")},
|
Capacity: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G")},
|
||||||
PersistentVolumeSource: v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{}},
|
PersistentVolumeSource: v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{}},
|
||||||
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
|
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
@ -1237,6 +1302,7 @@ func TestStorageObjectInUseProtectionFiltering(t *testing.T) {
|
||||||
Spec: v1.PersistentVolumeClaimSpec{
|
Spec: v1.PersistentVolumeClaimSpec{
|
||||||
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
|
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
|
||||||
Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G")}},
|
Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G")}},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1343,6 +1409,7 @@ func TestStorageObjectInUseProtectionFiltering(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFindingPreboundVolumes(t *testing.T) {
|
func TestFindingPreboundVolumes(t *testing.T) {
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
claim := &v1.PersistentVolumeClaim{
|
claim := &v1.PersistentVolumeClaim{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "claim01",
|
Name: "claim01",
|
||||||
|
@ -1352,6 +1419,7 @@ func TestFindingPreboundVolumes(t *testing.T) {
|
||||||
Spec: v1.PersistentVolumeClaimSpec{
|
Spec: v1.PersistentVolumeClaimSpec{
|
||||||
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
|
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
|
||||||
Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1Gi")}},
|
Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1Gi")}},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
claimRef, err := ref.GetReference(scheme.Scheme, claim)
|
claimRef, err := ref.GetReference(scheme.Scheme, claim)
|
||||||
|
|
|
@ -270,11 +270,11 @@ func checkVolumeSatisfyClaim(volume *v1.PersistentVolume, claim *v1.PersistentVo
|
||||||
return fmt.Errorf("storageClassName does not match")
|
return fmt.Errorf("storageClassName does not match")
|
||||||
}
|
}
|
||||||
|
|
||||||
isMisMatch, err := checkVolumeModeMisMatches(&claim.Spec, &volume.Spec)
|
isMismatch, err := checkVolumeModeMismatches(&claim.Spec, &volume.Spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error checking volumeMode: %v", err)
|
return fmt.Errorf("error checking volumeMode: %v", err)
|
||||||
}
|
}
|
||||||
if isMisMatch {
|
if isMismatch {
|
||||||
return fmt.Errorf("incompatible volumeMode")
|
return fmt.Errorf("incompatible volumeMode")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,7 +613,7 @@ func (ctrl *PersistentVolumeController) syncVolume(volume *v1.PersistentVolume)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
} else if claim.Spec.VolumeName == "" {
|
} else if claim.Spec.VolumeName == "" {
|
||||||
if isMisMatch, err := checkVolumeModeMisMatches(&claim.Spec, &volume.Spec); err != nil || isMisMatch {
|
if isMismatch, err := checkVolumeModeMismatches(&claim.Spec, &volume.Spec); err != nil || isMismatch {
|
||||||
// Binding for the volume won't be called in syncUnboundClaim,
|
// Binding for the volume won't be called in syncUnboundClaim,
|
||||||
// because findBestMatchForClaim won't return the volume due to volumeMode mismatch.
|
// because findBestMatchForClaim won't return the volume due to volumeMode mismatch.
|
||||||
volumeMsg := fmt.Sprintf("Cannot bind PersistentVolume to requested PersistentVolumeClaim %q due to incompatible volumeMode.", claim.Name)
|
volumeMsg := fmt.Sprintf("Cannot bind PersistentVolume to requested PersistentVolumeClaim %q due to incompatible volumeMode.", claim.Name)
|
||||||
|
|
|
@ -426,6 +426,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeTestPVC(name, size, node string, pvcBoundState int, pvName, resourceVersion string, className *string) *v1.PersistentVolumeClaim {
|
func makeTestPVC(name, size, node string, pvcBoundState int, pvName, resourceVersion string, className *string) *v1.PersistentVolumeClaim {
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
pvc := &v1.PersistentVolumeClaim{
|
pvc := &v1.PersistentVolumeClaim{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
Kind: "PersistentVolumeClaim",
|
Kind: "PersistentVolumeClaim",
|
||||||
|
@ -445,6 +446,7 @@ func makeTestPVC(name, size, node string, pvcBoundState int, pvName, resourceVer
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
StorageClassName: className,
|
StorageClassName: className,
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,6 +464,7 @@ func makeTestPVC(name, size, node string, pvcBoundState int, pvName, resourceVer
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeBadPVC() *v1.PersistentVolumeClaim {
|
func makeBadPVC() *v1.PersistentVolumeClaim {
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
return &v1.PersistentVolumeClaim{
|
return &v1.PersistentVolumeClaim{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "bad-pvc",
|
Name: "bad-pvc",
|
||||||
|
@ -477,11 +480,13 @@ func makeBadPVC() *v1.PersistentVolumeClaim {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
StorageClassName: &waitClass,
|
StorageClassName: &waitClass,
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeTestPV(name, node, capacity, version string, boundToPVC *v1.PersistentVolumeClaim, className string) *v1.PersistentVolume {
|
func makeTestPV(name, node, capacity, version string, boundToPVC *v1.PersistentVolumeClaim, className string) *v1.PersistentVolume {
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
@ -492,6 +497,7 @@ func makeTestPV(name, node, capacity, version string, boundToPVC *v1.PersistentV
|
||||||
v1.ResourceName(v1.ResourceStorage): resource.MustParse(capacity),
|
v1.ResourceName(v1.ResourceStorage): resource.MustParse(capacity),
|
||||||
},
|
},
|
||||||
StorageClassName: className,
|
StorageClassName: className,
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeStatus{
|
Status: v1.PersistentVolumeStatus{
|
||||||
Phase: v1.VolumeAvailable,
|
Phase: v1.VolumeAvailable,
|
||||||
|
|
|
@ -217,6 +217,7 @@ const (
|
||||||
|
|
||||||
// owner: @screeley44
|
// owner: @screeley44
|
||||||
// alpha: v1.9
|
// alpha: v1.9
|
||||||
|
// beta: v1.13
|
||||||
//
|
//
|
||||||
// Enable Block volume support in containers.
|
// Enable Block volume support in containers.
|
||||||
BlockVolume utilfeature.Feature = "BlockVolume"
|
BlockVolume utilfeature.Feature = "BlockVolume"
|
||||||
|
@ -433,7 +434,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS
|
||||||
CSIDriverRegistry: {Default: false, PreRelease: utilfeature.Alpha},
|
CSIDriverRegistry: {Default: false, PreRelease: utilfeature.Alpha},
|
||||||
CSINodeInfo: {Default: false, PreRelease: utilfeature.Alpha},
|
CSINodeInfo: {Default: false, PreRelease: utilfeature.Alpha},
|
||||||
CustomPodDNS: {Default: true, PreRelease: utilfeature.Beta},
|
CustomPodDNS: {Default: true, PreRelease: utilfeature.Beta},
|
||||||
BlockVolume: {Default: false, PreRelease: utilfeature.Alpha},
|
BlockVolume: {Default: true, PreRelease: utilfeature.Beta},
|
||||||
StorageObjectInUseProtection: {Default: true, PreRelease: utilfeature.GA},
|
StorageObjectInUseProtection: {Default: true, PreRelease: utilfeature.GA},
|
||||||
ResourceLimitsPriorityFunction: {Default: false, PreRelease: utilfeature.Alpha},
|
ResourceLimitsPriorityFunction: {Default: false, PreRelease: utilfeature.Alpha},
|
||||||
SupportIPVSProxyMode: {Default: true, PreRelease: utilfeature.GA},
|
SupportIPVSProxyMode: {Default: true, PreRelease: utilfeature.GA},
|
||||||
|
|
|
@ -46,12 +46,14 @@ import (
|
||||||
|
|
||||||
func TestFindAndAddNewPods_FindAndRemoveDeletedPods(t *testing.T) {
|
func TestFindAndAddNewPods_FindAndRemoveDeletedPods(t *testing.T) {
|
||||||
// create dswp
|
// create dswp
|
||||||
|
mode := v1.PersistentVolumeFilesystem
|
||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "dswp-test-volume-name",
|
Name: "dswp-test-volume-name",
|
||||||
},
|
},
|
||||||
Spec: v1.PersistentVolumeSpec{
|
Spec: v1.PersistentVolumeSpec{
|
||||||
ClaimRef: &v1.ObjectReference{Namespace: "ns", Name: "file-bound"},
|
ClaimRef: &v1.ObjectReference{Namespace: "ns", Name: "file-bound"},
|
||||||
|
VolumeMode: &mode,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
pvc := &v1.PersistentVolumeClaim{
|
pvc := &v1.PersistentVolumeClaim{
|
||||||
|
@ -453,6 +455,7 @@ func TestCreateVolumeSpec_Invalid_Block_VolumeMounts(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckVolumeFSResize(t *testing.T) {
|
func TestCheckVolumeFSResize(t *testing.T) {
|
||||||
|
mode := v1.PersistentVolumeFilesystem
|
||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "dswp-test-volume-name",
|
Name: "dswp-test-volume-name",
|
||||||
|
@ -461,6 +464,7 @@ func TestCheckVolumeFSResize(t *testing.T) {
|
||||||
PersistentVolumeSource: v1.PersistentVolumeSource{RBD: &v1.RBDPersistentVolumeSource{}},
|
PersistentVolumeSource: v1.PersistentVolumeSource{RBD: &v1.RBDPersistentVolumeSource{}},
|
||||||
Capacity: volumeCapacity(1),
|
Capacity: volumeCapacity(1),
|
||||||
ClaimRef: &v1.ObjectReference{Namespace: "ns", Name: "file-bound"},
|
ClaimRef: &v1.ObjectReference{Namespace: "ns", Name: "file-bound"},
|
||||||
|
VolumeMode: &mode,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
pvc := &v1.PersistentVolumeClaim{
|
pvc := &v1.PersistentVolumeClaim{
|
||||||
|
|
|
@ -950,6 +950,7 @@ func Test_GenerateUnmapDeviceFunc_Plugin_Not_Found(t *testing.T) {
|
||||||
func Test_Run_Positive_VolumeFSResizeControllerAttachEnabled(t *testing.T) {
|
func Test_Run_Positive_VolumeFSResizeControllerAttachEnabled(t *testing.T) {
|
||||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExpandInUsePersistentVolumes, true)()
|
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExpandInUsePersistentVolumes, true)()
|
||||||
|
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "pv",
|
Name: "pv",
|
||||||
|
@ -957,6 +958,7 @@ func Test_Run_Positive_VolumeFSResizeControllerAttachEnabled(t *testing.T) {
|
||||||
},
|
},
|
||||||
Spec: v1.PersistentVolumeSpec{
|
Spec: v1.PersistentVolumeSpec{
|
||||||
ClaimRef: &v1.ObjectReference{Name: "pvc"},
|
ClaimRef: &v1.ObjectReference{Name: "pvc"},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
pvc := &v1.PersistentVolumeClaim{
|
pvc := &v1.PersistentVolumeClaim{
|
||||||
|
@ -966,6 +968,7 @@ func Test_Run_Positive_VolumeFSResizeControllerAttachEnabled(t *testing.T) {
|
||||||
},
|
},
|
||||||
Spec: v1.PersistentVolumeClaimSpec{
|
Spec: v1.PersistentVolumeClaimSpec{
|
||||||
VolumeName: "pv",
|
VolumeName: "pv",
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
pod := &v1.Pod{
|
pod := &v1.Pod{
|
||||||
|
|
|
@ -167,6 +167,7 @@ func TestGetExtraSupplementalGroupsForPod(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "pvA",
|
Name: "pvA",
|
||||||
|
@ -183,6 +184,7 @@ func TestGetExtraSupplementalGroupsForPod(t *testing.T) {
|
||||||
ClaimRef: &v1.ObjectReference{
|
ClaimRef: &v1.ObjectReference{
|
||||||
Name: claim.ObjectMeta.Name,
|
Name: claim.ObjectMeta.Name,
|
||||||
},
|
},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
kubeClient := fake.NewSimpleClientset(node, pod, pv, claim)
|
kubeClient := fake.NewSimpleClientset(node, pod, pv, claim)
|
||||||
|
@ -273,6 +275,7 @@ func createObjects() (*v1.Node, *v1.Pod, *v1.PersistentVolume, *v1.PersistentVol
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "pvA",
|
Name: "pvA",
|
||||||
|
@ -286,6 +289,7 @@ func createObjects() (*v1.Node, *v1.Pod, *v1.PersistentVolume, *v1.PersistentVol
|
||||||
ClaimRef: &v1.ObjectReference{
|
ClaimRef: &v1.ObjectReference{
|
||||||
Name: "claimA",
|
Name: "claimA",
|
||||||
},
|
},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
claim := &v1.PersistentVolumeClaim{
|
claim := &v1.PersistentVolumeClaim{
|
||||||
|
|
|
@ -254,6 +254,7 @@ func TestPluginVolume(t *testing.T) {
|
||||||
|
|
||||||
func TestPluginPersistentVolume(t *testing.T) {
|
func TestPluginPersistentVolume(t *testing.T) {
|
||||||
lun := int32(0)
|
lun := int32(0)
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
vol := &v1.PersistentVolume{
|
vol := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "vol1",
|
Name: "vol1",
|
||||||
|
@ -266,6 +267,7 @@ func TestPluginPersistentVolume(t *testing.T) {
|
||||||
Lun: &lun,
|
Lun: &lun,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
doTestPlugin(t, volume.NewSpecFromPersistentVolume(vol, false))
|
doTestPlugin(t, volume.NewSpecFromPersistentVolume(vol, false))
|
||||||
|
@ -285,6 +287,7 @@ func TestPluginVolumeWWIDs(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPluginPersistentVolumeWWIDs(t *testing.T) {
|
func TestPluginPersistentVolumeWWIDs(t *testing.T) {
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
vol := &v1.PersistentVolume{
|
vol := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "vol1",
|
Name: "vol1",
|
||||||
|
@ -296,6 +299,7 @@ func TestPluginPersistentVolumeWWIDs(t *testing.T) {
|
||||||
FSType: "ext4",
|
FSType: "ext4",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
doTestPlugin(t, volume.NewSpecFromPersistentVolume(vol, false))
|
doTestPlugin(t, volume.NewSpecFromPersistentVolume(vol, false))
|
||||||
|
@ -314,6 +318,7 @@ func TestPluginVolumeNoDiskInfo(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPluginPersistentVolumeNoDiskInfo(t *testing.T) {
|
func TestPluginPersistentVolumeNoDiskInfo(t *testing.T) {
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
vol := &v1.PersistentVolume{
|
vol := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "vol1",
|
Name: "vol1",
|
||||||
|
@ -324,6 +329,7 @@ func TestPluginPersistentVolumeNoDiskInfo(t *testing.T) {
|
||||||
FSType: "ext4",
|
FSType: "ext4",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
doTestPluginNilMounter(t, volume.NewSpecFromPersistentVolume(vol, false))
|
doTestPluginNilMounter(t, volume.NewSpecFromPersistentVolume(vol, false))
|
||||||
|
@ -337,6 +343,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
lun := int32(0)
|
lun := int32(0)
|
||||||
|
fs := v1.PersistentVolumeFilesystem
|
||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "pvA",
|
Name: "pvA",
|
||||||
|
@ -352,6 +359,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
|
||||||
ClaimRef: &v1.ObjectReference{
|
ClaimRef: &v1.ObjectReference{
|
||||||
Name: "claimA",
|
Name: "claimA",
|
||||||
},
|
},
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,6 +370,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
|
||||||
},
|
},
|
||||||
Spec: v1.PersistentVolumeClaimSpec{
|
Spec: v1.PersistentVolumeClaimSpec{
|
||||||
VolumeName: "pvA",
|
VolumeName: "pvA",
|
||||||
|
VolumeMode: &fs,
|
||||||
},
|
},
|
||||||
Status: v1.PersistentVolumeClaimStatus{
|
Status: v1.PersistentVolumeClaimStatus{
|
||||||
Phase: v1.ClaimBound,
|
Phase: v1.ClaimBound,
|
||||||
|
|
|
@ -641,7 +641,7 @@ message Container {
|
||||||
repeated VolumeMount volumeMounts = 9;
|
repeated VolumeMount volumeMounts = 9;
|
||||||
|
|
||||||
// volumeDevices is the list of block devices to be used by the container.
|
// volumeDevices is the list of block devices to be used by the container.
|
||||||
// This is an alpha feature and may change in the future.
|
// This is a beta feature.
|
||||||
// +patchMergeKey=devicePath
|
// +patchMergeKey=devicePath
|
||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +optional
|
// +optional
|
||||||
|
@ -2320,7 +2320,7 @@ message PersistentVolumeClaimSpec {
|
||||||
|
|
||||||
// volumeMode defines what type of volume is required by the claim.
|
// volumeMode defines what type of volume is required by the claim.
|
||||||
// Value of Filesystem is implied when not included in claim spec.
|
// Value of Filesystem is implied when not included in claim spec.
|
||||||
// This is an alpha feature and may change in the future.
|
// This is a beta feature.
|
||||||
// +optional
|
// +optional
|
||||||
optional string volumeMode = 6;
|
optional string volumeMode = 6;
|
||||||
|
|
||||||
|
@ -2536,7 +2536,7 @@ message PersistentVolumeSpec {
|
||||||
|
|
||||||
// volumeMode defines if a volume is intended to be used with a formatted filesystem
|
// volumeMode defines if a volume is intended to be used with a formatted filesystem
|
||||||
// or to remain in raw block state. Value of Filesystem is implied when not included in spec.
|
// or to remain in raw block state. Value of Filesystem is implied when not included in spec.
|
||||||
// This is an alpha feature and may change in the future.
|
// This is a beta feature.
|
||||||
// +optional
|
// +optional
|
||||||
optional string volumeMode = 8;
|
optional string volumeMode = 8;
|
||||||
|
|
||||||
|
|
|
@ -326,7 +326,7 @@ type PersistentVolumeSpec struct {
|
||||||
MountOptions []string `json:"mountOptions,omitempty" protobuf:"bytes,7,opt,name=mountOptions"`
|
MountOptions []string `json:"mountOptions,omitempty" protobuf:"bytes,7,opt,name=mountOptions"`
|
||||||
// volumeMode defines if a volume is intended to be used with a formatted filesystem
|
// volumeMode defines if a volume is intended to be used with a formatted filesystem
|
||||||
// or to remain in raw block state. Value of Filesystem is implied when not included in spec.
|
// or to remain in raw block state. Value of Filesystem is implied when not included in spec.
|
||||||
// This is an alpha feature and may change in the future.
|
// This is a beta feature.
|
||||||
// +optional
|
// +optional
|
||||||
VolumeMode *PersistentVolumeMode `json:"volumeMode,omitempty" protobuf:"bytes,8,opt,name=volumeMode,casttype=PersistentVolumeMode"`
|
VolumeMode *PersistentVolumeMode `json:"volumeMode,omitempty" protobuf:"bytes,8,opt,name=volumeMode,casttype=PersistentVolumeMode"`
|
||||||
// NodeAffinity defines constraints that limit what nodes this volume can be accessed from.
|
// NodeAffinity defines constraints that limit what nodes this volume can be accessed from.
|
||||||
|
@ -455,7 +455,7 @@ type PersistentVolumeClaimSpec struct {
|
||||||
StorageClassName *string `json:"storageClassName,omitempty" protobuf:"bytes,5,opt,name=storageClassName"`
|
StorageClassName *string `json:"storageClassName,omitempty" protobuf:"bytes,5,opt,name=storageClassName"`
|
||||||
// volumeMode defines what type of volume is required by the claim.
|
// volumeMode defines what type of volume is required by the claim.
|
||||||
// Value of Filesystem is implied when not included in claim spec.
|
// Value of Filesystem is implied when not included in claim spec.
|
||||||
// This is an alpha feature and may change in the future.
|
// This is a beta feature.
|
||||||
// +optional
|
// +optional
|
||||||
VolumeMode *PersistentVolumeMode `json:"volumeMode,omitempty" protobuf:"bytes,6,opt,name=volumeMode,casttype=PersistentVolumeMode"`
|
VolumeMode *PersistentVolumeMode `json:"volumeMode,omitempty" protobuf:"bytes,6,opt,name=volumeMode,casttype=PersistentVolumeMode"`
|
||||||
// This field requires the VolumeSnapshotDataSource alpha feature gate to be
|
// This field requires the VolumeSnapshotDataSource alpha feature gate to be
|
||||||
|
@ -2114,7 +2114,7 @@ type Container struct {
|
||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
VolumeMounts []VolumeMount `json:"volumeMounts,omitempty" patchStrategy:"merge" patchMergeKey:"mountPath" protobuf:"bytes,9,rep,name=volumeMounts"`
|
VolumeMounts []VolumeMount `json:"volumeMounts,omitempty" patchStrategy:"merge" patchMergeKey:"mountPath" protobuf:"bytes,9,rep,name=volumeMounts"`
|
||||||
// volumeDevices is the list of block devices to be used by the container.
|
// volumeDevices is the list of block devices to be used by the container.
|
||||||
// This is an alpha feature and may change in the future.
|
// This is a beta feature.
|
||||||
// +patchMergeKey=devicePath
|
// +patchMergeKey=devicePath
|
||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +optional
|
// +optional
|
||||||
|
|
|
@ -321,7 +321,7 @@ var map_Container = map[string]string{
|
||||||
"env": "List of environment variables to set in the container. Cannot be updated.",
|
"env": "List of environment variables to set in the container. Cannot be updated.",
|
||||||
"resources": "Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/",
|
"resources": "Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/",
|
||||||
"volumeMounts": "Pod volumes to mount into the container's filesystem. Cannot be updated.",
|
"volumeMounts": "Pod volumes to mount into the container's filesystem. Cannot be updated.",
|
||||||
"volumeDevices": "volumeDevices is the list of block devices to be used by the container. This is an alpha feature and may change in the future.",
|
"volumeDevices": "volumeDevices is the list of block devices to be used by the container. This is a beta feature.",
|
||||||
"livenessProbe": "Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes",
|
"livenessProbe": "Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes",
|
||||||
"readinessProbe": "Periodic probe of container service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes",
|
"readinessProbe": "Periodic probe of container service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes",
|
||||||
"lifecycle": "Actions that the management system should take in response to container lifecycle events. Cannot be updated.",
|
"lifecycle": "Actions that the management system should take in response to container lifecycle events. Cannot be updated.",
|
||||||
|
@ -1222,7 +1222,7 @@ var map_PersistentVolumeClaimSpec = map[string]string{
|
||||||
"resources": "Resources represents the minimum resources the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources",
|
"resources": "Resources represents the minimum resources the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources",
|
||||||
"volumeName": "VolumeName is the binding reference to the PersistentVolume backing this claim.",
|
"volumeName": "VolumeName is the binding reference to the PersistentVolume backing this claim.",
|
||||||
"storageClassName": "Name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1",
|
"storageClassName": "Name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1",
|
||||||
"volumeMode": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is an alpha feature and may change in the future.",
|
"volumeMode": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is a beta feature.",
|
||||||
"dataSource": "This field requires the VolumeSnapshotDataSource alpha feature gate to be enabled and currently VolumeSnapshot is the only supported data source. If the provisioner can support VolumeSnapshot data source, it will create a new volume and data will be restored to the volume at the same time. If the provisioner does not support VolumeSnapshot data source, volume will not be created and the failure will be reported as an event. In the future, we plan to support more data source types and the behavior of the provisioner may change.",
|
"dataSource": "This field requires the VolumeSnapshotDataSource alpha feature gate to be enabled and currently VolumeSnapshot is the only supported data source. If the provisioner can support VolumeSnapshot data source, it will create a new volume and data will be restored to the volume at the same time. If the provisioner does not support VolumeSnapshot data source, volume will not be created and the failure will be reported as an event. In the future, we plan to support more data source types and the behavior of the provisioner may change.",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1300,7 +1300,7 @@ var map_PersistentVolumeSpec = map[string]string{
|
||||||
"persistentVolumeReclaimPolicy": "What happens to a persistent volume when released from its claim. Valid options are Retain (default for manually created PersistentVolumes), Delete (default for dynamically provisioned PersistentVolumes), and Recycle (deprecated). Recycle must be supported by the volume plugin underlying this PersistentVolume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#reclaiming",
|
"persistentVolumeReclaimPolicy": "What happens to a persistent volume when released from its claim. Valid options are Retain (default for manually created PersistentVolumes), Delete (default for dynamically provisioned PersistentVolumes), and Recycle (deprecated). Recycle must be supported by the volume plugin underlying this PersistentVolume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#reclaiming",
|
||||||
"storageClassName": "Name of StorageClass to which this persistent volume belongs. Empty value means that this volume does not belong to any StorageClass.",
|
"storageClassName": "Name of StorageClass to which this persistent volume belongs. Empty value means that this volume does not belong to any StorageClass.",
|
||||||
"mountOptions": "A list of mount options, e.g. [\"ro\", \"soft\"]. Not validated - mount will simply fail if one is invalid. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#mount-options",
|
"mountOptions": "A list of mount options, e.g. [\"ro\", \"soft\"]. Not validated - mount will simply fail if one is invalid. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#mount-options",
|
||||||
"volumeMode": "volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec. This is an alpha feature and may change in the future.",
|
"volumeMode": "volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec. This is a beta feature.",
|
||||||
"nodeAffinity": "NodeAffinity defines constraints that limit what nodes this volume can be accessed from. This field influences the scheduling of pods that use this volume.",
|
"nodeAffinity": "NodeAffinity defines constraints that limit what nodes this volume can be accessed from. This field influences the scheduling of pods that use this volume.",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ var upgradeTests = []upgrades.Test{
|
||||||
&apps.DaemonSetUpgradeTest{},
|
&apps.DaemonSetUpgradeTest{},
|
||||||
&upgrades.IngressUpgradeTest{},
|
&upgrades.IngressUpgradeTest{},
|
||||||
&upgrades.AppArmorUpgradeTest{},
|
&upgrades.AppArmorUpgradeTest{},
|
||||||
|
&storage.VolumeModeDowngradeTest{},
|
||||||
}
|
}
|
||||||
|
|
||||||
var gpuUpgradeTests = []upgrades.Test{
|
var gpuUpgradeTests = []upgrades.Test{
|
||||||
|
|
|
@ -218,11 +218,7 @@ var _ = utils.SIGDescribe("PersistentVolumes-local ", func() {
|
||||||
if testVolType == GCELocalSSDVolumeType {
|
if testVolType == GCELocalSSDVolumeType {
|
||||||
serialStr = " [Serial]"
|
serialStr = " [Serial]"
|
||||||
}
|
}
|
||||||
alphaStr := ""
|
ctxString := fmt.Sprintf("[Volume type: %s]%v", testVolType, serialStr)
|
||||||
if testVolType == BlockLocalVolumeType {
|
|
||||||
alphaStr = " [Feature:BlockVolume]"
|
|
||||||
}
|
|
||||||
ctxString := fmt.Sprintf("[Volume type: %s]%v%v", testVolType, serialStr, alphaStr)
|
|
||||||
testMode := immediateMode
|
testMode := immediateMode
|
||||||
|
|
||||||
Context(ctxString, func() {
|
Context(ctxString, func() {
|
||||||
|
|
|
@ -186,7 +186,7 @@ func testProvisioning(input *provisioningTestInput) {
|
||||||
TestDynamicProvisioning(input.testCase, input.cs, input.pvc, input.sc)
|
TestDynamicProvisioning(input.testCase, input.cs, input.pvc, input.sc)
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should create and delete block persistent volumes [Feature:BlockVolume]", func() {
|
It("should create and delete block persistent volumes", func() {
|
||||||
if !input.dInfo.IsBlockSupported {
|
if !input.dInfo.IsBlockSupported {
|
||||||
framework.Skipf("Driver %q does not support BlockVolume - skipping", input.dInfo.Name)
|
framework.Skipf("Driver %q does not support BlockVolume - skipping", input.dInfo.Name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,6 @@ func InitVolumeModeTestSuite() TestSuite {
|
||||||
return &volumeModeTestSuite{
|
return &volumeModeTestSuite{
|
||||||
tsInfo: TestSuiteInfo{
|
tsInfo: TestSuiteInfo{
|
||||||
name: "volumeMode",
|
name: "volumeMode",
|
||||||
featureTag: "[Feature:BlockVolume]",
|
|
||||||
testPatterns: []testpatterns.TestPattern{
|
testPatterns: []testpatterns.TestPattern{
|
||||||
testpatterns.FsVolModePreprovisionedPV,
|
testpatterns.FsVolModePreprovisionedPV,
|
||||||
testpatterns.FsVolModeDynamicPV,
|
testpatterns.FsVolModeDynamicPV,
|
||||||
|
@ -304,10 +303,10 @@ func testVolumeModeSuccessForPreprovisionedPV(input *volumeModeTestInput) {
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
By("Checking if persistent volume exists as expected volume mode")
|
By("Checking if persistent volume exists as expected volume mode")
|
||||||
checkVolumeModeOfPath(pod, input.volMode, "/mnt/volume1")
|
utils.CheckVolumeModeOfPath(pod, input.volMode, "/mnt/volume1")
|
||||||
|
|
||||||
By("Checking if read/write to persistent volume works properly")
|
By("Checking if read/write to persistent volume works properly")
|
||||||
checkReadWriteToPath(pod, input.volMode, "/mnt/volume1")
|
utils.CheckReadWriteToPath(pod, input.volMode, "/mnt/volume1")
|
||||||
})
|
})
|
||||||
// TODO(mkimuram): Add more tests
|
// TODO(mkimuram): Add more tests
|
||||||
}
|
}
|
||||||
|
@ -366,10 +365,10 @@ func testVolumeModeSuccessForDynamicPV(input *volumeModeTestInput) {
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
By("Checking if persistent volume exists as expected volume mode")
|
By("Checking if persistent volume exists as expected volume mode")
|
||||||
checkVolumeModeOfPath(pod, input.volMode, "/mnt/volume1")
|
utils.CheckVolumeModeOfPath(pod, input.volMode, "/mnt/volume1")
|
||||||
|
|
||||||
By("Checking if read/write to persistent volume works properly")
|
By("Checking if read/write to persistent volume works properly")
|
||||||
checkReadWriteToPath(pod, input.volMode, "/mnt/volume1")
|
utils.CheckReadWriteToPath(pod, input.volMode, "/mnt/volume1")
|
||||||
})
|
})
|
||||||
// TODO(mkimuram): Add more tests
|
// TODO(mkimuram): Add more tests
|
||||||
}
|
}
|
||||||
|
@ -401,45 +400,3 @@ func generateConfigsForPreprovisionedPVTest(scName string, volBindMode storagev1
|
||||||
|
|
||||||
return scConfig, pvConfig, pvcConfig
|
return scConfig, pvConfig, pvcConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkVolumeModeOfPath(pod *v1.Pod, volMode v1.PersistentVolumeMode, path string) {
|
|
||||||
if volMode == v1.PersistentVolumeBlock {
|
|
||||||
// Check if block exists
|
|
||||||
utils.VerifyExecInPodSucceed(pod, fmt.Sprintf("test -b %s", path))
|
|
||||||
|
|
||||||
// Double check that it's not directory
|
|
||||||
utils.VerifyExecInPodFail(pod, fmt.Sprintf("test -d %s", path), 1)
|
|
||||||
} else {
|
|
||||||
// Check if directory exists
|
|
||||||
utils.VerifyExecInPodSucceed(pod, fmt.Sprintf("test -d %s", path))
|
|
||||||
|
|
||||||
// Double check that it's not block
|
|
||||||
utils.VerifyExecInPodFail(pod, fmt.Sprintf("test -b %s", path), 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkReadWriteToPath(pod *v1.Pod, volMode v1.PersistentVolumeMode, path string) {
|
|
||||||
if volMode == v1.PersistentVolumeBlock {
|
|
||||||
// random -> file1
|
|
||||||
utils.VerifyExecInPodSucceed(pod, "dd if=/dev/urandom of=/tmp/file1 bs=64 count=1")
|
|
||||||
// file1 -> dev (write to dev)
|
|
||||||
utils.VerifyExecInPodSucceed(pod, fmt.Sprintf("dd if=/tmp/file1 of=%s bs=64 count=1", path))
|
|
||||||
// dev -> file2 (read from dev)
|
|
||||||
utils.VerifyExecInPodSucceed(pod, fmt.Sprintf("dd if=%s of=/tmp/file2 bs=64 count=1", path))
|
|
||||||
// file1 == file2 (check contents)
|
|
||||||
utils.VerifyExecInPodSucceed(pod, "diff /tmp/file1 /tmp/file2")
|
|
||||||
// Clean up temp files
|
|
||||||
utils.VerifyExecInPodSucceed(pod, "rm -f /tmp/file1 /tmp/file2")
|
|
||||||
|
|
||||||
// Check that writing file to block volume fails
|
|
||||||
utils.VerifyExecInPodFail(pod, fmt.Sprintf("echo 'Hello world.' > %s/file1.txt", path), 1)
|
|
||||||
} else {
|
|
||||||
// text -> file1 (write to file)
|
|
||||||
utils.VerifyExecInPodSucceed(pod, fmt.Sprintf("echo 'Hello world.' > %s/file1.txt", path))
|
|
||||||
// grep file1 (read from file and check contents)
|
|
||||||
utils.VerifyExecInPodSucceed(pod, fmt.Sprintf("grep 'Hello world.' %s/file1.txt", path))
|
|
||||||
|
|
||||||
// Check that writing to directory as block volume fails
|
|
||||||
utils.VerifyExecInPodFail(pod, fmt.Sprintf("dd if=/dev/urandom of=%s bs=64 count=1", path), 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -441,3 +441,45 @@ func PrivilegedTestPSPClusterRoleBinding(client clientset.Interface,
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CheckVolumeModeOfPath(pod *v1.Pod, volMode v1.PersistentVolumeMode, path string) {
|
||||||
|
if volMode == v1.PersistentVolumeBlock {
|
||||||
|
// Check if block exists
|
||||||
|
VerifyExecInPodSucceed(pod, fmt.Sprintf("test -b %s", path))
|
||||||
|
|
||||||
|
// Double check that it's not directory
|
||||||
|
VerifyExecInPodFail(pod, fmt.Sprintf("test -d %s", path), 1)
|
||||||
|
} else {
|
||||||
|
// Check if directory exists
|
||||||
|
VerifyExecInPodSucceed(pod, fmt.Sprintf("test -d %s", path))
|
||||||
|
|
||||||
|
// Double check that it's not block
|
||||||
|
VerifyExecInPodFail(pod, fmt.Sprintf("test -b %s", path), 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckReadWriteToPath(pod *v1.Pod, volMode v1.PersistentVolumeMode, path string) {
|
||||||
|
if volMode == v1.PersistentVolumeBlock {
|
||||||
|
// random -> file1
|
||||||
|
VerifyExecInPodSucceed(pod, "dd if=/dev/urandom of=/tmp/file1 bs=64 count=1")
|
||||||
|
// file1 -> dev (write to dev)
|
||||||
|
VerifyExecInPodSucceed(pod, fmt.Sprintf("dd if=/tmp/file1 of=%s bs=64 count=1", path))
|
||||||
|
// dev -> file2 (read from dev)
|
||||||
|
VerifyExecInPodSucceed(pod, fmt.Sprintf("dd if=%s of=/tmp/file2 bs=64 count=1", path))
|
||||||
|
// file1 == file2 (check contents)
|
||||||
|
VerifyExecInPodSucceed(pod, "diff /tmp/file1 /tmp/file2")
|
||||||
|
// Clean up temp files
|
||||||
|
VerifyExecInPodSucceed(pod, "rm -f /tmp/file1 /tmp/file2")
|
||||||
|
|
||||||
|
// Check that writing file to block volume fails
|
||||||
|
VerifyExecInPodFail(pod, fmt.Sprintf("echo 'Hello world.' > %s/file1.txt", path), 1)
|
||||||
|
} else {
|
||||||
|
// text -> file1 (write to file)
|
||||||
|
VerifyExecInPodSucceed(pod, fmt.Sprintf("echo 'Hello world.' > %s/file1.txt", path))
|
||||||
|
// grep file1 (read from file and check contents)
|
||||||
|
VerifyExecInPodSucceed(pod, fmt.Sprintf("grep 'Hello world.' %s/file1.txt", path))
|
||||||
|
|
||||||
|
// Check that writing to directory as block volume fails
|
||||||
|
VerifyExecInPodFail(pod, fmt.Sprintf("dd if=/dev/urandom of=%s bs=64 count=1", path), 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,12 +7,18 @@ load(
|
||||||
|
|
||||||
go_library(
|
go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = ["persistent_volumes.go"],
|
srcs = [
|
||||||
|
"persistent_volumes.go",
|
||||||
|
"volume_mode.go",
|
||||||
|
],
|
||||||
importpath = "k8s.io/kubernetes/test/e2e/upgrades/storage",
|
importpath = "k8s.io/kubernetes/test/e2e/upgrades/storage",
|
||||||
deps = [
|
deps = [
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
|
||||||
"//test/e2e/framework:go_default_library",
|
"//test/e2e/framework:go_default_library",
|
||||||
|
"//test/e2e/storage/utils:go_default_library",
|
||||||
"//test/e2e/upgrades:go_default_library",
|
"//test/e2e/upgrades:go_default_library",
|
||||||
"//vendor/github.com/onsi/ginkgo:go_default_library",
|
"//vendor/github.com/onsi/ginkgo:go_default_library",
|
||||||
"//vendor/github.com/onsi/gomega:go_default_library",
|
"//vendor/github.com/onsi/gomega:go_default_library",
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
|
"k8s.io/kubernetes/test/e2e/framework"
|
||||||
|
"k8s.io/kubernetes/test/e2e/storage/utils"
|
||||||
|
"k8s.io/kubernetes/test/e2e/upgrades"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
const devicePath = "/mnt/volume1"
|
||||||
|
|
||||||
|
// VolumeModeDowngradeTest tests that a VolumeMode Block PV is not mistakenly
|
||||||
|
// formatted and mounted like a nil/Filesystem PV after a downgrade to a version
|
||||||
|
// where the BlockVolume feature is disabled
|
||||||
|
type VolumeModeDowngradeTest struct {
|
||||||
|
pvSource *v1.PersistentVolumeSource
|
||||||
|
pv *v1.PersistentVolume
|
||||||
|
pvc *v1.PersistentVolumeClaim
|
||||||
|
pod *v1.Pod
|
||||||
|
}
|
||||||
|
|
||||||
|
func (VolumeModeDowngradeTest) Name() string {
|
||||||
|
return "[sig-storage] volume-mode-downgrade"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *VolumeModeDowngradeTest) Skip(upgCtx upgrades.UpgradeContext) bool {
|
||||||
|
if !framework.ProviderIs("openstack", "gce", "aws", "gke", "vsphere", "azure") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only run when downgrading from >= 1.13 to < 1.13
|
||||||
|
blockVersion := version.MustParseSemantic("1.13.0-alpha.0")
|
||||||
|
if upgCtx.Versions[0].Version.LessThan(blockVersion) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if !upgCtx.Versions[1].Version.LessThan(blockVersion) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup creates a block pv and then verifies that a pod can consume it. The pod writes data to the volume.
|
||||||
|
func (t *VolumeModeDowngradeTest) Setup(f *framework.Framework) {
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
cs := f.ClientSet
|
||||||
|
ns := f.Namespace.Name
|
||||||
|
|
||||||
|
By("Creating a PVC")
|
||||||
|
block := v1.PersistentVolumeBlock
|
||||||
|
pvcConfig := framework.PersistentVolumeClaimConfig{
|
||||||
|
StorageClassName: nil,
|
||||||
|
VolumeMode: &block,
|
||||||
|
}
|
||||||
|
t.pvc = framework.MakePersistentVolumeClaim(pvcConfig, ns)
|
||||||
|
t.pvc, err = framework.CreatePVC(cs, ns, t.pvc)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
err = framework.WaitForPersistentVolumeClaimPhase(v1.ClaimBound, cs, ns, t.pvc.Name, framework.Poll, framework.ClaimProvisionTimeout)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
t.pvc, err = cs.CoreV1().PersistentVolumeClaims(t.pvc.Namespace).Get(t.pvc.Name, metav1.GetOptions{})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
t.pv, err = cs.CoreV1().PersistentVolumes().Get(t.pvc.Spec.VolumeName, metav1.GetOptions{})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Consuming the PVC before downgrade")
|
||||||
|
t.pod, err = framework.CreateSecPod(cs, ns, []*v1.PersistentVolumeClaim{t.pvc}, false, "", false, false, framework.SELinuxLabel, nil, framework.PodStartTimeout)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
By("Checking if PV exists as expected volume mode")
|
||||||
|
utils.CheckVolumeModeOfPath(t.pod, block, devicePath)
|
||||||
|
|
||||||
|
By("Checking if read/write to PV works properly")
|
||||||
|
utils.CheckReadWriteToPath(t.pod, block, devicePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test waits for the downgrade to complete, and then verifies that a pod can no
|
||||||
|
// longer consume the pv as it is not mapped nor mounted into the pod
|
||||||
|
func (t *VolumeModeDowngradeTest) Test(f *framework.Framework, done <-chan struct{}, upgrade upgrades.UpgradeType) {
|
||||||
|
By("Waiting for downgrade to finish")
|
||||||
|
<-done
|
||||||
|
|
||||||
|
By("Verifying that nothing exists at the device path in the pod")
|
||||||
|
utils.VerifyExecInPodFail(t.pod, fmt.Sprintf("test -e %s", devicePath), 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Teardown cleans up any remaining resources.
|
||||||
|
func (t *VolumeModeDowngradeTest) Teardown(f *framework.Framework) {
|
||||||
|
By("Deleting the pod")
|
||||||
|
framework.ExpectNoError(framework.DeletePodWithWait(f, f.ClientSet, t.pod))
|
||||||
|
|
||||||
|
By("Deleting the PVC")
|
||||||
|
framework.ExpectNoError(f.ClientSet.CoreV1().PersistentVolumeClaims(t.pvc.Namespace).Delete(t.pvc.Name, nil))
|
||||||
|
|
||||||
|
By("Waiting for the PV to be deleted")
|
||||||
|
framework.ExpectNoError(framework.WaitForPersistentVolumeDeleted(f.ClientSet, t.pv.Name, 5*time.Second, 20*time.Minute))
|
||||||
|
}
|
Loading…
Reference in New Issue