Merge pull request #60195 from humblec/glusterfs-pvspec-3

Refactor GlusterFS PV spec.
pull/58/head
k8s-ci-robot 2018-11-08 00:24:39 -08:00 committed by GitHub
commit 3c10143967
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1718 additions and 1085 deletions

View File

@ -4,6 +4,7 @@ API rule violation: names_match,k8s.io/api/core/v1,ContainerStatus,LastTerminati
API rule violation: names_match,k8s.io/api/core/v1,DaemonEndpoint,Port API rule violation: names_match,k8s.io/api/core/v1,DaemonEndpoint,Port
API rule violation: names_match,k8s.io/api/core/v1,Event,ReportingController API rule violation: names_match,k8s.io/api/core/v1,Event,ReportingController
API rule violation: names_match,k8s.io/api/core/v1,FCVolumeSource,WWIDs API rule violation: names_match,k8s.io/api/core/v1,FCVolumeSource,WWIDs
API rule violation: names_match,k8s.io/api/core/v1,GlusterfsPersistentVolumeSource,EndpointsName
API rule violation: names_match,k8s.io/api/core/v1,GlusterfsVolumeSource,EndpointsName API rule violation: names_match,k8s.io/api/core/v1,GlusterfsVolumeSource,EndpointsName
API rule violation: names_match,k8s.io/api/core/v1,ISCSIPersistentVolumeSource,DiscoveryCHAPAuth API rule violation: names_match,k8s.io/api/core/v1,ISCSIPersistentVolumeSource,DiscoveryCHAPAuth
API rule violation: names_match,k8s.io/api/core/v1,ISCSIPersistentVolumeSource,SessionCHAPAuth API rule violation: names_match,k8s.io/api/core/v1,ISCSIPersistentVolumeSource,SessionCHAPAuth

View File

@ -84125,6 +84125,31 @@
} }
} }
}, },
"io.k8s.api.core.v1.GlusterfsPersistentVolumeSource": {
"description": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.",
"required": [
"endpoints",
"path"
],
"properties": {
"endpoints": {
"description": "EndpointsName is the endpoint name that details Glusterfs topology. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",
"type": "string"
},
"endpointsNamespace": {
"description": "EndpointsNamespace is the namespace that contains Glusterfs endpoint. If this field is empty, the EndpointNamespace defaults to the same namespace as the bound PVC. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",
"type": "string"
},
"path": {
"description": "Path is the Glusterfs volume path. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",
"type": "string"
},
"readOnly": {
"description": "ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",
"type": "boolean"
}
}
},
"io.k8s.api.core.v1.GlusterfsVolumeSource": { "io.k8s.api.core.v1.GlusterfsVolumeSource": {
"description": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.", "description": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.",
"required": [ "required": [
@ -85424,7 +85449,7 @@
}, },
"glusterfs": { "glusterfs": {
"description": "Glusterfs represents a Glusterfs volume that is attached to a host and exposed to the pod. Provisioned by an admin. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md", "description": "Glusterfs represents a Glusterfs volume that is attached to a host and exposed to the pod. Provisioned by an admin. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md",
"$ref": "#/definitions/io.k8s.api.core.v1.GlusterfsVolumeSource" "$ref": "#/definitions/io.k8s.api.core.v1.GlusterfsPersistentVolumeSource"
}, },
"hostPath": { "hostPath": {
"description": "HostPath represents a directory on the host. Provisioned by a developer or tester. This is useful for single-node development and testing only! On-host storage is not supported in any way and WILL NOT WORK in a multi-node cluster. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath", "description": "HostPath represents a directory on the host. Provisioned by a developer or tester. This is useful for single-node development and testing only! On-host storage is not supported in any way and WILL NOT WORK in a multi-node cluster. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath",

View File

@ -20217,7 +20217,7 @@
"description": "HostPath represents a directory on the host. Provisioned by a developer or tester. This is useful for single-node development and testing only! On-host storage is not supported in any way and WILL NOT WORK in a multi-node cluster. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath" "description": "HostPath represents a directory on the host. Provisioned by a developer or tester. This is useful for single-node development and testing only! On-host storage is not supported in any way and WILL NOT WORK in a multi-node cluster. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
}, },
"glusterfs": { "glusterfs": {
"$ref": "v1.GlusterfsVolumeSource", "$ref": "v1.GlusterfsPersistentVolumeSource",
"description": "Glusterfs represents a Glusterfs volume that is attached to a host and exposed to the pod. Provisioned by an admin. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md" "description": "Glusterfs represents a Glusterfs volume that is attached to a host and exposed to the pod. Provisioned by an admin. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md"
}, },
"nfs": { "nfs": {
@ -20401,8 +20401,8 @@
"id": "v1.HostPathType", "id": "v1.HostPathType",
"properties": {} "properties": {}
}, },
"v1.GlusterfsVolumeSource": { "v1.GlusterfsPersistentVolumeSource": {
"id": "v1.GlusterfsVolumeSource", "id": "v1.GlusterfsPersistentVolumeSource",
"description": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.", "description": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.",
"required": [ "required": [
"endpoints", "endpoints",
@ -20420,6 +20420,10 @@
"readOnly": { "readOnly": {
"type": "boolean", "type": "boolean",
"description": "ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod" "description": "ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod"
},
"endpointsNamespace": {
"type": "string",
"description": "EndpointsNamespace is the namespace that contains Glusterfs endpoint. If this field is empty, the EndpointNamespace defaults to the same namespace as the bound PVC. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod"
} }
} }
}, },
@ -21568,6 +21572,28 @@
} }
} }
}, },
"v1.GlusterfsVolumeSource": {
"id": "v1.GlusterfsVolumeSource",
"description": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.",
"required": [
"endpoints",
"path"
],
"properties": {
"endpoints": {
"type": "string",
"description": "EndpointsName is the endpoint name that details Glusterfs topology. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod"
},
"path": {
"type": "string",
"description": "Path is the Glusterfs volume path. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod"
},
"readOnly": {
"type": "boolean",
"description": "ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod"
}
}
},
"v1.PersistentVolumeClaimVolumeSource": { "v1.PersistentVolumeClaimVolumeSource": {
"id": "v1.PersistentVolumeClaimVolumeSource", "id": "v1.PersistentVolumeClaimVolumeSource",
"description": "PersistentVolumeClaimVolumeSource references the user's PVC in the same namespace. This volume finds the bound PV and mounts that volume for the pod. A PersistentVolumeClaimVolumeSource is, essentially, a wrapper around another type of volume that is owned by someone else (the system).", "description": "PersistentVolumeClaimVolumeSource references the user's PVC in the same namespace. This volume finds the bound PV and mounts that volume for the pod. A PersistentVolumeClaimVolumeSource is, essentially, a wrapper around another type of volume that is owned by someone else (the system).",

View File

@ -2864,54 +2864,6 @@ The resulting set of endpoints can be viewed as:<br>
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_glusterfsvolumesource">v1.GlusterfsVolumeSource</h3>
<div class="paragraph">
<p>Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">endpoints</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">EndpointsName is the endpoint name that details Glusterfs topology. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod">https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">path</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Path is the Glusterfs volume path. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod">https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">readOnly</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod">https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody>
</table>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_nodestatus">v1.NodeStatus</h3> <h3 id="_v1_nodestatus">v1.NodeStatus</h3>
@ -3016,6 +2968,54 @@ The resulting set of endpoints can be viewed as:<br>
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_glusterfsvolumesource">v1.GlusterfsVolumeSource</h3>
<div class="paragraph">
<p>Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">endpoints</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">EndpointsName is the endpoint name that details Glusterfs topology. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod">https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">path</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Path is the Glusterfs volume path. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod">https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">readOnly</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod">https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody>
</table>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_handler">v1.Handler</h3> <h3 id="_v1_handler">v1.Handler</h3>
@ -4116,7 +4116,7 @@ Examples:<br>
<td class="tableblock halign-left valign-top"><p class="tableblock">glusterfs</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">glusterfs</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Glusterfs represents a Glusterfs volume that is attached to a host and exposed to the pod. Provisioned by an admin. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md">https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md</a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Glusterfs represents a Glusterfs volume that is attached to a host and exposed to the pod. Provisioned by an admin. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md">https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md</a></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_glusterfsvolumesource">v1.GlusterfsVolumeSource</a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_glusterfspersistentvolumesource">v1.GlusterfsPersistentVolumeSource</a></p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
</tr> </tr>
<tr> <tr>
@ -8229,6 +8229,61 @@ Examples:<br>
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_glusterfspersistentvolumesource">v1.GlusterfsPersistentVolumeSource</h3>
<div class="paragraph">
<p>Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">endpoints</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">EndpointsName is the endpoint name that details Glusterfs topology. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod">https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">path</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Path is the Glusterfs volume path. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod">https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">readOnly</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod">https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">endpointsNamespace</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">EndpointsNamespace is the namespace that contains Glusterfs endpoint. If this field is empty, the EndpointNamespace defaults to the same namespace as the bound PVC. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod">https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod</a></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">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_csipersistentvolumesource">v1.CSIPersistentVolumeSource</h3> <h3 id="_v1_csipersistentvolumesource">v1.CSIPersistentVolumeSource</h3>
@ -9553,6 +9608,54 @@ More info: <a href="https://kubernetes.io/docs/concepts/workloads/pods/pod-lifec
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_scopedresourceselectorrequirement">v1.ScopedResourceSelectorRequirement</h3>
<div class="paragraph">
<p>A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator that relates the scope name and values.</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">scopeName</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The name of the scope that the selector applies to.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">operator</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Represents a scope&#8217;s relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">values</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.</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">string array</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_podspec">v1.PodSpec</h3> <h3 id="_v1_podspec">v1.PodSpec</h3>
@ -9790,54 +9893,6 @@ More info: <a href="https://kubernetes.io/docs/concepts/workloads/pods/pod-lifec
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_scopedresourceselectorrequirement">v1.ScopedResourceSelectorRequirement</h3>
<div class="paragraph">
<p>A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator that relates the scope name and values.</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">scopeName</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The name of the scope that the selector applies to.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">operator</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Represents a scope&#8217;s relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">values</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.</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">string array</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_eventlist">v1.EventList</h3> <h3 id="_v1_eventlist">v1.EventList</h3>

View File

@ -175,7 +175,7 @@ type PersistentVolumeSource struct {
HostPath *HostPathVolumeSource HostPath *HostPathVolumeSource
// Glusterfs represents a Glusterfs volume that is attached to a host and exposed to the pod // Glusterfs represents a Glusterfs volume that is attached to a host and exposed to the pod
// +optional // +optional
Glusterfs *GlusterfsVolumeSource Glusterfs *GlusterfsPersistentVolumeSource
// NFS represents an NFS mount on the host that shares a pod's lifetime // NFS represents an NFS mount on the host that shares a pod's lifetime
// +optional // +optional
NFS *NFSVolumeSource NFS *NFSVolumeSource
@ -935,6 +935,30 @@ type GlusterfsVolumeSource struct {
ReadOnly bool ReadOnly bool
} }
// Represents a Glusterfs mount that lasts the lifetime of a pod.
// Glusterfs volumes do not support ownership management or SELinux relabeling.
type GlusterfsPersistentVolumeSource struct {
// EndpointsName is the endpoint name that details Glusterfs topology.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
EndpointsName string
// Path is the Glusterfs volume path.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
Path string
// ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions.
// Defaults to false.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
// +optional
ReadOnly bool
// EndpointsNamespace is the namespace that contains Glusterfs endpoint.
// If this field is empty, the EndpointNamespace defaults to the same namespace as the bound PVC.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
// +optional
EndpointsNamespace *string
}
// Represents a Rados Block Device mount that lasts the lifetime of a pod. // Represents a Rados Block Device mount that lasts the lifetime of a pod.
// RBD volumes support ownership management and SELinux relabeling. // RBD volumes support ownership management and SELinux relabeling.
type RBDVolumeSource struct { type RBDVolumeSource struct {

View File

@ -610,6 +610,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil { }); err != nil {
return err return err
} }
if err := s.AddGeneratedConversionFunc((*v1.GlusterfsPersistentVolumeSource)(nil), (*core.GlusterfsPersistentVolumeSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_GlusterfsPersistentVolumeSource_To_core_GlusterfsPersistentVolumeSource(a.(*v1.GlusterfsPersistentVolumeSource), b.(*core.GlusterfsPersistentVolumeSource), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*core.GlusterfsPersistentVolumeSource)(nil), (*v1.GlusterfsPersistentVolumeSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_core_GlusterfsPersistentVolumeSource_To_v1_GlusterfsPersistentVolumeSource(a.(*core.GlusterfsPersistentVolumeSource), b.(*v1.GlusterfsPersistentVolumeSource), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.GlusterfsVolumeSource)(nil), (*core.GlusterfsVolumeSource)(nil), func(a, b interface{}, scope conversion.Scope) error { if err := s.AddGeneratedConversionFunc((*v1.GlusterfsVolumeSource)(nil), (*core.GlusterfsVolumeSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_GlusterfsVolumeSource_To_core_GlusterfsVolumeSource(a.(*v1.GlusterfsVolumeSource), b.(*core.GlusterfsVolumeSource), scope) return Convert_v1_GlusterfsVolumeSource_To_core_GlusterfsVolumeSource(a.(*v1.GlusterfsVolumeSource), b.(*core.GlusterfsVolumeSource), scope)
}); err != nil { }); err != nil {
@ -3602,6 +3612,32 @@ func Convert_core_GitRepoVolumeSource_To_v1_GitRepoVolumeSource(in *core.GitRepo
return autoConvert_core_GitRepoVolumeSource_To_v1_GitRepoVolumeSource(in, out, s) return autoConvert_core_GitRepoVolumeSource_To_v1_GitRepoVolumeSource(in, out, s)
} }
func autoConvert_v1_GlusterfsPersistentVolumeSource_To_core_GlusterfsPersistentVolumeSource(in *v1.GlusterfsPersistentVolumeSource, out *core.GlusterfsPersistentVolumeSource, s conversion.Scope) error {
out.EndpointsName = in.EndpointsName
out.Path = in.Path
out.ReadOnly = in.ReadOnly
out.EndpointsNamespace = (*string)(unsafe.Pointer(in.EndpointsNamespace))
return nil
}
// Convert_v1_GlusterfsPersistentVolumeSource_To_core_GlusterfsPersistentVolumeSource is an autogenerated conversion function.
func Convert_v1_GlusterfsPersistentVolumeSource_To_core_GlusterfsPersistentVolumeSource(in *v1.GlusterfsPersistentVolumeSource, out *core.GlusterfsPersistentVolumeSource, s conversion.Scope) error {
return autoConvert_v1_GlusterfsPersistentVolumeSource_To_core_GlusterfsPersistentVolumeSource(in, out, s)
}
func autoConvert_core_GlusterfsPersistentVolumeSource_To_v1_GlusterfsPersistentVolumeSource(in *core.GlusterfsPersistentVolumeSource, out *v1.GlusterfsPersistentVolumeSource, s conversion.Scope) error {
out.EndpointsName = in.EndpointsName
out.Path = in.Path
out.ReadOnly = in.ReadOnly
out.EndpointsNamespace = (*string)(unsafe.Pointer(in.EndpointsNamespace))
return nil
}
// Convert_core_GlusterfsPersistentVolumeSource_To_v1_GlusterfsPersistentVolumeSource is an autogenerated conversion function.
func Convert_core_GlusterfsPersistentVolumeSource_To_v1_GlusterfsPersistentVolumeSource(in *core.GlusterfsPersistentVolumeSource, out *v1.GlusterfsPersistentVolumeSource, s conversion.Scope) error {
return autoConvert_core_GlusterfsPersistentVolumeSource_To_v1_GlusterfsPersistentVolumeSource(in, out, s)
}
func autoConvert_v1_GlusterfsVolumeSource_To_core_GlusterfsVolumeSource(in *v1.GlusterfsVolumeSource, out *core.GlusterfsVolumeSource, s conversion.Scope) error { func autoConvert_v1_GlusterfsVolumeSource_To_core_GlusterfsVolumeSource(in *v1.GlusterfsVolumeSource, out *core.GlusterfsVolumeSource, s conversion.Scope) error {
out.EndpointsName = in.EndpointsName out.EndpointsName = in.EndpointsName
out.Path = in.Path out.Path = in.Path
@ -4932,7 +4968,7 @@ func autoConvert_v1_PersistentVolumeSource_To_core_PersistentVolumeSource(in *v1
out.GCEPersistentDisk = (*core.GCEPersistentDiskVolumeSource)(unsafe.Pointer(in.GCEPersistentDisk)) out.GCEPersistentDisk = (*core.GCEPersistentDiskVolumeSource)(unsafe.Pointer(in.GCEPersistentDisk))
out.AWSElasticBlockStore = (*core.AWSElasticBlockStoreVolumeSource)(unsafe.Pointer(in.AWSElasticBlockStore)) out.AWSElasticBlockStore = (*core.AWSElasticBlockStoreVolumeSource)(unsafe.Pointer(in.AWSElasticBlockStore))
out.HostPath = (*core.HostPathVolumeSource)(unsafe.Pointer(in.HostPath)) out.HostPath = (*core.HostPathVolumeSource)(unsafe.Pointer(in.HostPath))
out.Glusterfs = (*core.GlusterfsVolumeSource)(unsafe.Pointer(in.Glusterfs)) out.Glusterfs = (*core.GlusterfsPersistentVolumeSource)(unsafe.Pointer(in.Glusterfs))
out.NFS = (*core.NFSVolumeSource)(unsafe.Pointer(in.NFS)) out.NFS = (*core.NFSVolumeSource)(unsafe.Pointer(in.NFS))
out.RBD = (*core.RBDPersistentVolumeSource)(unsafe.Pointer(in.RBD)) out.RBD = (*core.RBDPersistentVolumeSource)(unsafe.Pointer(in.RBD))
out.ISCSI = (*core.ISCSIPersistentVolumeSource)(unsafe.Pointer(in.ISCSI)) out.ISCSI = (*core.ISCSIPersistentVolumeSource)(unsafe.Pointer(in.ISCSI))
@ -4963,7 +4999,7 @@ func autoConvert_core_PersistentVolumeSource_To_v1_PersistentVolumeSource(in *co
out.GCEPersistentDisk = (*v1.GCEPersistentDiskVolumeSource)(unsafe.Pointer(in.GCEPersistentDisk)) out.GCEPersistentDisk = (*v1.GCEPersistentDiskVolumeSource)(unsafe.Pointer(in.GCEPersistentDisk))
out.AWSElasticBlockStore = (*v1.AWSElasticBlockStoreVolumeSource)(unsafe.Pointer(in.AWSElasticBlockStore)) out.AWSElasticBlockStore = (*v1.AWSElasticBlockStoreVolumeSource)(unsafe.Pointer(in.AWSElasticBlockStore))
out.HostPath = (*v1.HostPathVolumeSource)(unsafe.Pointer(in.HostPath)) out.HostPath = (*v1.HostPathVolumeSource)(unsafe.Pointer(in.HostPath))
out.Glusterfs = (*v1.GlusterfsVolumeSource)(unsafe.Pointer(in.Glusterfs)) out.Glusterfs = (*v1.GlusterfsPersistentVolumeSource)(unsafe.Pointer(in.Glusterfs))
out.NFS = (*v1.NFSVolumeSource)(unsafe.Pointer(in.NFS)) out.NFS = (*v1.NFSVolumeSource)(unsafe.Pointer(in.NFS))
out.RBD = (*v1.RBDPersistentVolumeSource)(unsafe.Pointer(in.RBD)) out.RBD = (*v1.RBDPersistentVolumeSource)(unsafe.Pointer(in.RBD))
out.Quobyte = (*v1.QuobyteVolumeSource)(unsafe.Pointer(in.Quobyte)) out.Quobyte = (*v1.QuobyteVolumeSource)(unsafe.Pointer(in.Quobyte))

View File

@ -903,6 +903,26 @@ func validateGlusterfsVolumeSource(glusterfs *core.GlusterfsVolumeSource, fldPat
} }
return allErrs return allErrs
} }
func validateGlusterfsPersistentVolumeSource(glusterfs *core.GlusterfsPersistentVolumeSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(glusterfs.EndpointsName) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("endpoints"), ""))
}
if len(glusterfs.Path) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("path"), ""))
}
if glusterfs.EndpointsNamespace != nil {
endpointNs := glusterfs.EndpointsNamespace
if *endpointNs == "" {
allErrs = append(allErrs, field.Invalid(fldPath.Child("endpointsNamespace"), *endpointNs, "if the endpointnamespace is set, it must be a valid namespace name"))
} else {
for _, msg := range ValidateNamespaceName(*endpointNs, false) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("endpointsNamespace"), *endpointNs, msg))
}
}
}
return allErrs
}
func validateFlockerVolumeSource(flocker *core.FlockerVolumeSource, fldPath *field.Path) field.ErrorList { func validateFlockerVolumeSource(flocker *core.FlockerVolumeSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{} allErrs := field.ErrorList{}
@ -1567,7 +1587,7 @@ func ValidatePersistentVolume(pv *core.PersistentVolume) field.ErrorList {
allErrs = append(allErrs, field.Forbidden(specPath.Child("glusterfs"), "may not specify more than 1 volume type")) allErrs = append(allErrs, field.Forbidden(specPath.Child("glusterfs"), "may not specify more than 1 volume type"))
} else { } else {
numVolumes++ numVolumes++
allErrs = append(allErrs, validateGlusterfsVolumeSource(pv.Spec.Glusterfs, specPath.Child("glusterfs"))...) allErrs = append(allErrs, validateGlusterfsPersistentVolumeSource(pv.Spec.Glusterfs, specPath.Child("glusterfs"))...)
} }
} }
if pv.Spec.Flocker != nil { if pv.Spec.Flocker != nil {

View File

@ -1774,6 +1774,60 @@ func TestValidateGlusterfs(t *testing.T) {
} }
} }
func TestValidateGlusterfsPersistentVolumeSource(t *testing.T) {
var epNs *string
namespace := ""
epNs = &namespace
testCases := []struct {
name string
gfs *core.GlusterfsPersistentVolumeSource
errtype field.ErrorType
errfield string
}{
{
name: "missing endpointname",
gfs: &core.GlusterfsPersistentVolumeSource{EndpointsName: "", Path: "/tmp"},
errtype: field.ErrorTypeRequired,
errfield: "endpoints",
},
{
name: "missing path",
gfs: &core.GlusterfsPersistentVolumeSource{EndpointsName: "my-endpoint", Path: ""},
errtype: field.ErrorTypeRequired,
errfield: "path",
},
{
name: "non null endpointnamespace with empty string",
gfs: &core.GlusterfsPersistentVolumeSource{EndpointsName: "my-endpoint", Path: "/tmp", EndpointsNamespace: epNs},
errtype: field.ErrorTypeInvalid,
errfield: "endpointsNamespace",
},
{
name: "missing endpointname and path",
gfs: &core.GlusterfsPersistentVolumeSource{EndpointsName: "", Path: ""},
errtype: field.ErrorTypeRequired,
errfield: "endpoints",
},
}
for i, tc := range testCases {
errs := validateGlusterfsPersistentVolumeSource(tc.gfs, field.NewPath("field"))
if len(errs) > 0 && tc.errtype == "" {
t.Errorf("[%d: %q] unexpected error(s): %v", i, tc.name, errs)
} else if len(errs) == 0 && tc.errtype != "" {
t.Errorf("[%d: %q] expected error type %v", i, tc.name, tc.errtype)
} else if len(errs) >= 1 {
if errs[0].Type != tc.errtype {
t.Errorf("[%d: %q] expected error type %v, got %v", i, tc.name, tc.errtype, errs[0].Type)
} else if !strings.HasSuffix(errs[0].Field, "."+tc.errfield) {
t.Errorf("[%d: %q] expected error on field %q, got %q", i, tc.name, tc.errfield, errs[0].Field)
}
}
}
}
func TestValidateCSIVolumeSource(t *testing.T) { func TestValidateCSIVolumeSource(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string

View File

@ -1498,6 +1498,27 @@ func (in *GitRepoVolumeSource) DeepCopy() *GitRepoVolumeSource {
return out return out
} }
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GlusterfsPersistentVolumeSource) DeepCopyInto(out *GlusterfsPersistentVolumeSource) {
*out = *in
if in.EndpointsNamespace != nil {
in, out := &in.EndpointsNamespace, &out.EndpointsNamespace
*out = new(string)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlusterfsPersistentVolumeSource.
func (in *GlusterfsPersistentVolumeSource) DeepCopy() *GlusterfsPersistentVolumeSource {
if in == nil {
return nil
}
out := new(GlusterfsPersistentVolumeSource)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GlusterfsVolumeSource) DeepCopyInto(out *GlusterfsVolumeSource) { func (in *GlusterfsVolumeSource) DeepCopyInto(out *GlusterfsVolumeSource) {
*out = *in *out = *in
@ -2808,8 +2829,8 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) {
} }
if in.Glusterfs != nil { if in.Glusterfs != nil {
in, out := &in.Glusterfs, &out.Glusterfs in, out := &in.Glusterfs, &out.Glusterfs
*out = new(GlusterfsVolumeSource) *out = new(GlusterfsPersistentVolumeSource)
**out = **in (*in).DeepCopyInto(*out)
} }
if in.NFS != nil { if in.NFS != nil {
in, out := &in.NFS, &out.NFS in, out := &in.NFS, &out.NFS

View File

@ -494,7 +494,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ResourceName(v1.ResourceStorage): resource.MustParse("5G"), v1.ResourceName(v1.ResourceStorage): resource.MustParse("5G"),
}, },
PersistentVolumeSource: v1.PersistentVolumeSource{ PersistentVolumeSource: v1.PersistentVolumeSource{
Glusterfs: &v1.GlusterfsVolumeSource{}, Glusterfs: &v1.GlusterfsPersistentVolumeSource{},
}, },
AccessModes: []v1.PersistentVolumeAccessMode{ AccessModes: []v1.PersistentVolumeAccessMode{
v1.ReadWriteOnce, v1.ReadWriteOnce,
@ -539,7 +539,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ResourceName(v1.ResourceStorage): resource.MustParse("10G"), v1.ResourceName(v1.ResourceStorage): resource.MustParse("10G"),
}, },
PersistentVolumeSource: v1.PersistentVolumeSource{ PersistentVolumeSource: v1.PersistentVolumeSource{
Glusterfs: &v1.GlusterfsVolumeSource{}, Glusterfs: &v1.GlusterfsPersistentVolumeSource{},
}, },
AccessModes: []v1.PersistentVolumeAccessMode{ AccessModes: []v1.PersistentVolumeAccessMode{
v1.ReadWriteOnce, v1.ReadWriteOnce,
@ -582,7 +582,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G"), v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G"),
}, },
PersistentVolumeSource: v1.PersistentVolumeSource{ PersistentVolumeSource: v1.PersistentVolumeSource{
Glusterfs: &v1.GlusterfsVolumeSource{}, Glusterfs: &v1.GlusterfsPersistentVolumeSource{},
}, },
AccessModes: []v1.PersistentVolumeAccessMode{ AccessModes: []v1.PersistentVolumeAccessMode{
v1.ReadWriteOnce, v1.ReadWriteOnce,

View File

@ -929,6 +929,15 @@ func printGlusterfsVolumeSource(glusterfs *api.GlusterfsVolumeSource, w PrefixWr
glusterfs.EndpointsName, glusterfs.Path, glusterfs.ReadOnly) glusterfs.EndpointsName, glusterfs.Path, glusterfs.ReadOnly)
} }
func printGlusterfsPersistentVolumeSource(glusterfs *api.GlusterfsPersistentVolumeSource, w PrefixWriter) {
w.Write(LEVEL_2, "Type:\tGlusterfs (a Glusterfs mount on the host that shares a pod's lifetime)\n"+
" EndpointsName:\t%v\n"+
" EndpointsNamespace:\t%v\n"+
" Path:\t%v\n"+
" ReadOnly:\t%v\n",
glusterfs.EndpointsName, glusterfs.EndpointsNamespace, glusterfs.Path, glusterfs.ReadOnly)
}
func printPersistentVolumeClaimVolumeSource(claim *api.PersistentVolumeClaimVolumeSource, w PrefixWriter) { func printPersistentVolumeClaimVolumeSource(claim *api.PersistentVolumeClaimVolumeSource, w PrefixWriter) {
w.Write(LEVEL_2, "Type:\tPersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)\n"+ w.Write(LEVEL_2, "Type:\tPersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)\n"+
" ClaimName:\t%v\n"+ " ClaimName:\t%v\n"+
@ -1311,7 +1320,7 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) (
case pv.Spec.ISCSI != nil: case pv.Spec.ISCSI != nil:
printISCSIPersistentVolumeSource(pv.Spec.ISCSI, w) printISCSIPersistentVolumeSource(pv.Spec.ISCSI, w)
case pv.Spec.Glusterfs != nil: case pv.Spec.Glusterfs != nil:
printGlusterfsVolumeSource(pv.Spec.Glusterfs, w) printGlusterfsPersistentVolumeSource(pv.Spec.Glusterfs, w)
case pv.Spec.RBD != nil: case pv.Spec.RBD != nil:
printRBDPersistentVolumeSource(pv.Spec.RBD, w) printRBDPersistentVolumeSource(pv.Spec.RBD, w)
case pv.Spec.Quobyte != nil: case pv.Spec.Quobyte != nil:

View File

@ -982,7 +982,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "bar"}, ObjectMeta: metav1.ObjectMeta{Name: "bar"},
Spec: api.PersistentVolumeSpec{ Spec: api.PersistentVolumeSpec{
PersistentVolumeSource: api.PersistentVolumeSource{ PersistentVolumeSource: api.PersistentVolumeSource{
Glusterfs: &api.GlusterfsVolumeSource{}, Glusterfs: &api.GlusterfsPersistentVolumeSource{},
}, },
}, },
}, },

View File

@ -106,15 +106,30 @@ func (plugin *glusterfsPlugin) GetPluginName() string {
} }
func (plugin *glusterfsPlugin) GetVolumeName(spec *volume.Spec) (string, error) { func (plugin *glusterfsPlugin) GetVolumeName(spec *volume.Spec) (string, error) {
volumeSource, _, err := getVolumeSource(spec) var endpointName string
var endpointsNsPtr *string
volPath, _, err := getVolumeInfo(spec)
if err != nil { if err != nil {
return "", err return "", err
} }
return fmt.Sprintf( if spec.Volume != nil && spec.Volume.Glusterfs != nil {
"%v:%v", endpointName = spec.Volume.Glusterfs.EndpointsName
volumeSource.EndpointsName, } else if spec.PersistentVolume != nil &&
volumeSource.Path), nil spec.PersistentVolume.Spec.Glusterfs != nil {
endpointName = spec.PersistentVolume.Spec.Glusterfs.EndpointsName
endpointsNsPtr = spec.PersistentVolume.Spec.Glusterfs.EndpointsNamespace
if endpointsNsPtr != nil && *endpointsNsPtr != "" {
return fmt.Sprintf("%v:%v:%v", endpointName, *endpointsNsPtr, volPath), nil
}
return "", fmt.Errorf("invalid endpointsnamespace in provided glusterfs PV spec")
} else {
return "", fmt.Errorf("unable to fetch required parameters from provided glusterfs spec")
}
return fmt.Sprintf("%v:%v", endpointName, volPath), nil
} }
func (plugin *glusterfsPlugin) CanSupport(spec *volume.Spec) bool { func (plugin *glusterfsPlugin) CanSupport(spec *volume.Spec) bool {
@ -147,19 +162,17 @@ func (plugin *glusterfsPlugin) GetAccessModes() []v1.PersistentVolumeAccessMode
} }
func (plugin *glusterfsPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.Mounter, error) { func (plugin *glusterfsPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.Mounter, error) {
source, _, err := getVolumeSource(spec) epName, epNamespace, err := plugin.getEndpointNameAndNamespace(spec, pod.Namespace)
if err != nil { if err != nil {
glog.Errorf("failed to get gluster volumesource: %v", err)
return nil, err return nil, err
} }
epName := source.EndpointsName
// PVC/POD is in same namespace.
podNs := pod.Namespace
kubeClient := plugin.host.GetKubeClient() kubeClient := plugin.host.GetKubeClient()
if kubeClient == nil { if kubeClient == nil {
return nil, fmt.Errorf("failed to get kube client to initialize mounter") return nil, fmt.Errorf("failed to get kube client to initialize mounter")
} }
ep, err := kubeClient.CoreV1().Endpoints(podNs).Get(epName, metav1.GetOptions{}) ep, err := kubeClient.Core().Endpoints(epNamespace).Get(epName, metav1.GetOptions{})
if err != nil { if err != nil {
glog.Errorf("failed to get endpoint %s: %v", epName, err) glog.Errorf("failed to get endpoint %s: %v", epName, err)
return nil, err return nil, err
@ -168,8 +181,38 @@ func (plugin *glusterfsPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volu
return plugin.newMounterInternal(spec, ep, pod, plugin.host.GetMounter(plugin.GetPluginName())) return plugin.newMounterInternal(spec, ep, pod, plugin.host.GetMounter(plugin.GetPluginName()))
} }
func (plugin *glusterfsPlugin) getEndpointNameAndNamespace(spec *volume.Spec, defaultNamespace string) (string, string, error) {
if spec.Volume != nil && spec.Volume.Glusterfs != nil {
endpoints := spec.Volume.Glusterfs.EndpointsName
if endpoints == "" {
return "", "", fmt.Errorf("no glusterFS endpoint specified")
}
return endpoints, defaultNamespace, nil
} else if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.Glusterfs != nil {
endpoints := spec.PersistentVolume.Spec.Glusterfs.EndpointsName
endpointsNs := defaultNamespace
overriddenNs := spec.PersistentVolume.Spec.Glusterfs.EndpointsNamespace
if overriddenNs != nil {
if len(*overriddenNs) > 0 {
endpointsNs = *overriddenNs
} else {
return "", "", fmt.Errorf("endpointnamespace field set, but no endpointnamespace specified")
}
}
return endpoints, endpointsNs, nil
}
return "", "", fmt.Errorf("Spec does not reference a GlusterFS volume type")
}
func (plugin *glusterfsPlugin) newMounterInternal(spec *volume.Spec, ep *v1.Endpoints, pod *v1.Pod, mounter mount.Interface) (volume.Mounter, error) { func (plugin *glusterfsPlugin) newMounterInternal(spec *volume.Spec, ep *v1.Endpoints, pod *v1.Pod, mounter mount.Interface) (volume.Mounter, error) {
source, readOnly, _ := getVolumeSource(spec) volPath, readOnly, err := getVolumeInfo(spec)
if err != nil {
glog.Errorf("failed to get volumesource : %v", err)
return nil, err
}
return &glusterfsMounter{ return &glusterfsMounter{
glusterfs: &glusterfs{ glusterfs: &glusterfs{
volName: spec.Name(), volName: spec.Name(),
@ -179,7 +222,7 @@ func (plugin *glusterfsPlugin) newMounterInternal(spec *volume.Spec, ep *v1.Endp
MetricsProvider: volume.NewMetricsStatFS(plugin.host.GetPodVolumeDir(pod.UID, strings.EscapeQualifiedNameForDisk(glusterfsPluginName), spec.Name())), MetricsProvider: volume.NewMetricsStatFS(plugin.host.GetPodVolumeDir(pod.UID, strings.EscapeQualifiedNameForDisk(glusterfsPluginName), spec.Name())),
}, },
hosts: ep, hosts: ep,
path: source.Path, path: volPath,
readOnly: readOnly, readOnly: readOnly,
mountOptions: volutil.MountOptionFromSpec(spec), mountOptions: volutil.MountOptionFromSpec(spec),
}, nil }, nil
@ -411,15 +454,16 @@ func (b *glusterfsMounter) setUpAtInternal(dir string) error {
} }
func getVolumeSource(spec *volume.Spec) (*v1.GlusterfsVolumeSource, bool, error) { //getVolumeInfo returns 'path' and 'readonly' field values from the provided glusterfs spec.
func getVolumeInfo(spec *volume.Spec) (string, bool, error) {
if spec.Volume != nil && spec.Volume.Glusterfs != nil { if spec.Volume != nil && spec.Volume.Glusterfs != nil {
return spec.Volume.Glusterfs, spec.Volume.Glusterfs.ReadOnly, nil return spec.Volume.Glusterfs.Path, spec.Volume.Glusterfs.ReadOnly, nil
} else if spec.PersistentVolume != nil && } else if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.Glusterfs != nil { spec.PersistentVolume.Spec.Glusterfs != nil {
return spec.PersistentVolume.Spec.Glusterfs, spec.ReadOnly, nil return spec.PersistentVolume.Spec.Glusterfs.Path, spec.ReadOnly, nil
} }
return "", false, fmt.Errorf("Spec does not reference a Glusterfs volume type")
return nil, false, fmt.Errorf("Spec does not reference a Glusterfs volume type")
} }
func (plugin *glusterfsPlugin) NewProvisioner(options volume.VolumeOptions) (volume.Provisioner, error) { func (plugin *glusterfsPlugin) NewProvisioner(options volume.VolumeOptions) (volume.Provisioner, error) {
@ -778,7 +822,7 @@ func (p *glusterfsVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTop
return pv, nil return pv, nil
} }
func (p *glusterfsVolumeProvisioner) CreateVolume(gid int) (r *v1.GlusterfsVolumeSource, size int, volID string, err error) { func (p *glusterfsVolumeProvisioner) CreateVolume(gid int) (r *v1.GlusterfsPersistentVolumeSource, size int, volID string, err error) {
var clusterIDs []string var clusterIDs []string
customVolumeName := "" customVolumeName := ""
epServiceName := "" epServiceName := ""
@ -849,10 +893,11 @@ func (p *glusterfsVolumeProvisioner) CreateVolume(gid int) (r *v1.GlusterfsVolum
return nil, 0, "", fmt.Errorf("failed to create endpoint/service %v/%v: %v", epNamespace, epServiceName, err) return nil, 0, "", fmt.Errorf("failed to create endpoint/service %v/%v: %v", epNamespace, epServiceName, err)
} }
glog.V(3).Infof("dynamic endpoint %v and service %v ", endpoint, service) glog.V(3).Infof("dynamic endpoint %v and service %v ", endpoint, service)
return &v1.GlusterfsVolumeSource{ return &v1.GlusterfsPersistentVolumeSource{
EndpointsName: endpoint.Name, EndpointsName: endpoint.Name,
Path: volume.Name, EndpointsNamespace: &epNamespace,
ReadOnly: false, Path: volume.Name,
ReadOnly: false,
}, sz, volID, nil }, sz, volID, nil
} }

View File

@ -66,7 +66,7 @@ func TestCanSupport(t *testing.T) {
if plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{}}}}) { if plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{}}}}) {
t.Errorf("Expected false") t.Errorf("Expected false")
} }
if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{Glusterfs: &v1.GlusterfsVolumeSource{}}}}}) { if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{Glusterfs: &v1.GlusterfsPersistentVolumeSource{}}}}}) {
t.Errorf("Expected true") t.Errorf("Expected true")
} }
} }
@ -160,7 +160,7 @@ func TestPluginPersistentVolume(t *testing.T) {
}, },
Spec: v1.PersistentVolumeSpec{ Spec: v1.PersistentVolumeSpec{
PersistentVolumeSource: v1.PersistentVolumeSource{ PersistentVolumeSource: v1.PersistentVolumeSource{
Glusterfs: &v1.GlusterfsVolumeSource{EndpointsName: "ep", Path: "vol", ReadOnly: false}, Glusterfs: &v1.GlusterfsPersistentVolumeSource{EndpointsName: "ep", Path: "vol", ReadOnly: false},
}, },
}, },
} }
@ -181,7 +181,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
}, },
Spec: v1.PersistentVolumeSpec{ Spec: v1.PersistentVolumeSpec{
PersistentVolumeSource: v1.PersistentVolumeSource{ PersistentVolumeSource: v1.PersistentVolumeSource{
Glusterfs: &v1.GlusterfsVolumeSource{EndpointsName: "ep", Path: "vol", ReadOnly: false}, Glusterfs: &v1.GlusterfsPersistentVolumeSource{EndpointsName: "ep", Path: "vol", ReadOnly: false},
}, },
ClaimRef: &v1.ObjectReference{ ClaimRef: &v1.ObjectReference{
Name: "claimA", Name: "claimA",

File diff suppressed because it is too large Load Diff

View File

@ -1373,6 +1373,30 @@ message GitRepoVolumeSource {
optional string directory = 3; optional string directory = 3;
} }
// Represents a Glusterfs mount that lasts the lifetime of a pod.
// Glusterfs volumes do not support ownership management or SELinux relabeling.
message GlusterfsPersistentVolumeSource {
// EndpointsName is the endpoint name that details Glusterfs topology.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
optional string endpoints = 1;
// Path is the Glusterfs volume path.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
optional string path = 2;
// ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions.
// Defaults to false.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
// +optional
optional bool readOnly = 3;
// EndpointsNamespace is the namespace that contains Glusterfs endpoint.
// If this field is empty, the EndpointNamespace defaults to the same namespace as the bound PVC.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
// +optional
optional string endpointsNamespace = 4;
}
// Represents a Glusterfs mount that lasts the lifetime of a pod. // Represents a Glusterfs mount that lasts the lifetime of a pod.
// Glusterfs volumes do not support ownership management or SELinux relabeling. // Glusterfs volumes do not support ownership management or SELinux relabeling.
message GlusterfsVolumeSource { message GlusterfsVolumeSource {
@ -2389,7 +2413,7 @@ message PersistentVolumeSource {
// exposed to the pod. Provisioned by an admin. // exposed to the pod. Provisioned by an admin.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md // More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md
// +optional // +optional
optional GlusterfsVolumeSource glusterfs = 4; optional GlusterfsPersistentVolumeSource glusterfs = 4;
// NFS represents an NFS mount on the host. Provisioned by an admin. // NFS represents an NFS mount on the host. Provisioned by an admin.
// More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs // More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs

View File

@ -191,7 +191,7 @@ type PersistentVolumeSource struct {
// exposed to the pod. Provisioned by an admin. // exposed to the pod. Provisioned by an admin.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md // More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md
// +optional // +optional
Glusterfs *GlusterfsVolumeSource `json:"glusterfs,omitempty" protobuf:"bytes,4,opt,name=glusterfs"` Glusterfs *GlusterfsPersistentVolumeSource `json:"glusterfs,omitempty" protobuf:"bytes,4,opt,name=glusterfs"`
// NFS represents an NFS mount on the host. Provisioned by an admin. // NFS represents an NFS mount on the host. Provisioned by an admin.
// More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs // More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
// +optional // +optional
@ -636,6 +636,30 @@ type GlusterfsVolumeSource struct {
ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,3,opt,name=readOnly"` ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,3,opt,name=readOnly"`
} }
// Represents a Glusterfs mount that lasts the lifetime of a pod.
// Glusterfs volumes do not support ownership management or SELinux relabeling.
type GlusterfsPersistentVolumeSource struct {
// EndpointsName is the endpoint name that details Glusterfs topology.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
EndpointsName string `json:"endpoints" protobuf:"bytes,1,opt,name=endpoints"`
// Path is the Glusterfs volume path.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
Path string `json:"path" protobuf:"bytes,2,opt,name=path"`
// ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions.
// Defaults to false.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
// +optional
ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,3,opt,name=readOnly"`
// EndpointsNamespace is the namespace that contains Glusterfs endpoint.
// If this field is empty, the EndpointNamespace defaults to the same namespace as the bound PVC.
// More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod
// +optional
EndpointsNamespace *string `json:"endpointsNamespace,omitempty" protobuf:"bytes,4,opt,name=endpointsNamespace"`
}
// Represents a Rados Block Device mount that lasts the lifetime of a pod. // Represents a Rados Block Device mount that lasts the lifetime of a pod.
// RBD volumes support ownership management and SELinux relabeling. // RBD volumes support ownership management and SELinux relabeling.
type RBDVolumeSource struct { type RBDVolumeSource struct {

View File

@ -695,6 +695,18 @@ func (GitRepoVolumeSource) SwaggerDoc() map[string]string {
return map_GitRepoVolumeSource return map_GitRepoVolumeSource
} }
var map_GlusterfsPersistentVolumeSource = map[string]string{
"": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.",
"endpoints": "EndpointsName is the endpoint name that details Glusterfs topology. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",
"path": "Path is the Glusterfs volume path. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",
"readOnly": "ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",
"endpointsNamespace": "EndpointsNamespace is the namespace that contains Glusterfs endpoint. If this field is empty, the EndpointNamespace defaults to the same namespace as the bound PVC. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",
}
func (GlusterfsPersistentVolumeSource) SwaggerDoc() map[string]string {
return map_GlusterfsPersistentVolumeSource
}
var map_GlusterfsVolumeSource = map[string]string{ var map_GlusterfsVolumeSource = map[string]string{
"": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.", "": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.",
"endpoints": "EndpointsName is the endpoint name that details Glusterfs topology. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod", "endpoints": "EndpointsName is the endpoint name that details Glusterfs topology. More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod",

View File

@ -1498,6 +1498,27 @@ func (in *GitRepoVolumeSource) DeepCopy() *GitRepoVolumeSource {
return out return out
} }
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GlusterfsPersistentVolumeSource) DeepCopyInto(out *GlusterfsPersistentVolumeSource) {
*out = *in
if in.EndpointsNamespace != nil {
in, out := &in.EndpointsNamespace, &out.EndpointsNamespace
*out = new(string)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlusterfsPersistentVolumeSource.
func (in *GlusterfsPersistentVolumeSource) DeepCopy() *GlusterfsPersistentVolumeSource {
if in == nil {
return nil
}
out := new(GlusterfsPersistentVolumeSource)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GlusterfsVolumeSource) DeepCopyInto(out *GlusterfsVolumeSource) { func (in *GlusterfsVolumeSource) DeepCopyInto(out *GlusterfsVolumeSource) {
*out = *in *out = *in
@ -2806,8 +2827,8 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) {
} }
if in.Glusterfs != nil { if in.Glusterfs != nil {
in, out := &in.Glusterfs, &out.Glusterfs in, out := &in.Glusterfs, &out.Glusterfs
*out = new(GlusterfsVolumeSource) *out = new(GlusterfsPersistentVolumeSource)
**out = **in (*in).DeepCopyInto(*out)
} }
if in.NFS != nil { if in.NFS != nil {
in, out := &in.NFS, &out.NFS in, out := &in.NFS, &out.NFS

View File

@ -274,7 +274,7 @@ func (g *glusterFSDriver) GetPersistentVolumeSource(readOnly bool, fsType string
name := gtr.prefix + "-server" name := gtr.prefix + "-server"
return &v1.PersistentVolumeSource{ return &v1.PersistentVolumeSource{
Glusterfs: &v1.GlusterfsVolumeSource{ Glusterfs: &v1.GlusterfsPersistentVolumeSource{
EndpointsName: name, EndpointsName: name,
// 'test_vol' comes from test/images/volumes-tester/gluster/run_gluster.sh // 'test_vol' comes from test/images/volumes-tester/gluster/run_gluster.sh
Path: "test_vol", Path: "test_vol",