Merge pull request #46597 from dixudx/implement_proposal_34058

Automatic merge from submit-queue (batch tested with PRs 51113, 46597, 50397, 51052, 51166)

implement proposal 34058: hostPath volume type

**What this PR does / why we need it**:
implement proposal #34058

**Which issue this PR fixes** : fixes #46549

**Special notes for your reviewer**:
cc @thockin @luxas @euank PTAL
This commit is contained in:
Kubernetes Submit Queue 2017-08-23 23:16:27 -07:00 committed by GitHub
commit c041567b5a
64 changed files with 2314 additions and 896 deletions

View File

@ -59407,7 +59407,11 @@
], ],
"properties": { "properties": {
"path": { "path": {
"description": "Path of the directory on the host. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath", "description": "Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath",
"type": "string"
},
"type": {
"description": "Type for HostPath Volume Defaults to \"\" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath",
"type": "string" "type": "string"
} }
} }

View File

@ -4135,10 +4135,18 @@
"properties": { "properties": {
"path": { "path": {
"type": "string", "type": "string",
"description": "Path of the directory on the host. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath" "description": "Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
},
"type": {
"$ref": "v1.HostPathType",
"description": "Type for HostPath Volume Defaults to \"\" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
} }
} }
}, },
"v1.HostPathType": {
"id": "v1.HostPathType",
"properties": {}
},
"v1.EmptyDirVolumeSource": { "v1.EmptyDirVolumeSource": {
"id": "v1.EmptyDirVolumeSource", "id": "v1.EmptyDirVolumeSource",
"description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.", "description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.",

View File

@ -6273,10 +6273,18 @@
"properties": { "properties": {
"path": { "path": {
"type": "string", "type": "string",
"description": "Path of the directory on the host. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath" "description": "Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
},
"type": {
"$ref": "v1.HostPathType",
"description": "Type for HostPath Volume Defaults to \"\" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
} }
} }
}, },
"v1.HostPathType": {
"id": "v1.HostPathType",
"properties": {}
},
"v1.EmptyDirVolumeSource": { "v1.EmptyDirVolumeSource": {
"id": "v1.EmptyDirVolumeSource", "id": "v1.EmptyDirVolumeSource",
"description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.", "description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.",

View File

@ -1717,10 +1717,18 @@
"properties": { "properties": {
"path": { "path": {
"type": "string", "type": "string",
"description": "Path of the directory on the host. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath" "description": "Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
},
"type": {
"$ref": "v1.HostPathType",
"description": "Type for HostPath Volume Defaults to \"\" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
} }
} }
}, },
"v1.HostPathType": {
"id": "v1.HostPathType",
"properties": {}
},
"v1.EmptyDirVolumeSource": { "v1.EmptyDirVolumeSource": {
"id": "v1.EmptyDirVolumeSource", "id": "v1.EmptyDirVolumeSource",
"description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.", "description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.",

View File

@ -1772,10 +1772,18 @@
"properties": { "properties": {
"path": { "path": {
"type": "string", "type": "string",
"description": "Path of the directory on the host. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath" "description": "Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
},
"type": {
"$ref": "v1.HostPathType",
"description": "Type for HostPath Volume Defaults to \"\" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
} }
} }
}, },
"v1.HostPathType": {
"id": "v1.HostPathType",
"properties": {}
},
"v1.EmptyDirVolumeSource": { "v1.EmptyDirVolumeSource": {
"id": "v1.EmptyDirVolumeSource", "id": "v1.EmptyDirVolumeSource",
"description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.", "description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.",

View File

@ -1772,10 +1772,18 @@
"properties": { "properties": {
"path": { "path": {
"type": "string", "type": "string",
"description": "Path of the directory on the host. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath" "description": "Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
},
"type": {
"$ref": "v1.HostPathType",
"description": "Type for HostPath Volume Defaults to \"\" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
} }
} }
}, },
"v1.HostPathType": {
"id": "v1.HostPathType",
"properties": {}
},
"v1.EmptyDirVolumeSource": { "v1.EmptyDirVolumeSource": {
"id": "v1.EmptyDirVolumeSource", "id": "v1.EmptyDirVolumeSource",
"description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.", "description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.",

View File

@ -6827,10 +6827,18 @@
"properties": { "properties": {
"path": { "path": {
"type": "string", "type": "string",
"description": "Path of the directory on the host. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath" "description": "Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
},
"type": {
"$ref": "v1.HostPathType",
"description": "Type for HostPath Volume Defaults to \"\" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
} }
} }
}, },
"v1.HostPathType": {
"id": "v1.HostPathType",
"properties": {}
},
"v1.EmptyDirVolumeSource": { "v1.EmptyDirVolumeSource": {
"id": "v1.EmptyDirVolumeSource", "id": "v1.EmptyDirVolumeSource",
"description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.", "description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.",

View File

@ -1573,10 +1573,18 @@
"properties": { "properties": {
"path": { "path": {
"type": "string", "type": "string",
"description": "Path of the directory on the host. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath" "description": "Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
},
"type": {
"$ref": "v1.HostPathType",
"description": "Type for HostPath Volume Defaults to \"\" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
} }
} }
}, },
"v1.HostPathType": {
"id": "v1.HostPathType",
"properties": {}
},
"v1.EmptyDirVolumeSource": { "v1.EmptyDirVolumeSource": {
"id": "v1.EmptyDirVolumeSource", "id": "v1.EmptyDirVolumeSource",
"description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.", "description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.",

View File

@ -18998,10 +18998,18 @@
"properties": { "properties": {
"path": { "path": {
"type": "string", "type": "string",
"description": "Path of the directory on the host. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath" "description": "Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
},
"type": {
"$ref": "v1.HostPathType",
"description": "Type for HostPath Volume Defaults to \"\" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
} }
} }
}, },
"v1.HostPathType": {
"id": "v1.HostPathType",
"properties": {}
},
"v1.GlusterfsVolumeSource": { "v1.GlusterfsVolumeSource": {
"id": "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.", "description": "Represents a Glusterfs mount that lasts the lifetime of a pod. Glusterfs volumes do not support ownership management or SELinux relabeling.",

View File

@ -4588,6 +4588,10 @@ Examples:<br>
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_hostpathtype">v1.HostPathType</h3>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_initializers">v1.Initializers</h3> <h3 id="_v1_initializers">v1.Initializers</h3>
@ -5874,11 +5878,18 @@ Examples:<br>
<tbody> <tbody>
<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</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
</tr> </tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Type for HostPath Volume Defaults to "" More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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"><a href="#_v1_hostpathtype">v1.HostPathType</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@ -4949,6 +4949,10 @@ Examples:<br>
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_hostpathtype">v1.HostPathType</h3>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1beta2_replicaset">v1beta2.ReplicaSet</h3> <h3 id="_v1beta2_replicaset">v1beta2.ReplicaSet</h3>
@ -6084,11 +6088,18 @@ Examples:<br>
<tbody> <tbody>
<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</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
</tr> </tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Type for HostPath Volume Defaults to "" More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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"><a href="#_v1_hostpathtype">v1.HostPathType</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@ -1483,6 +1483,10 @@ When an object is created, the system will populate this list with the current s
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_types_uid">types.UID</h3>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_azurefilevolumesource">v1.AzureFileVolumeSource</h3> <h3 id="_v1_azurefilevolumesource">v1.AzureFileVolumeSource</h3>
@ -1531,10 +1535,6 @@ When an object is created, the system will populate this list with the current s
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_types_uid">types.UID</h3>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_iscsivolumesource">v1.ISCSIVolumeSource</h3> <h3 id="_v1_iscsivolumesource">v1.ISCSIVolumeSource</h3>
@ -3831,6 +3831,10 @@ Examples:<br>
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_hostpathtype">v1.HostPathType</h3>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_initializers">v1.Initializers</h3> <h3 id="_v1_initializers">v1.Initializers</h3>
@ -4842,11 +4846,18 @@ Examples:<br>
<tbody> <tbody>
<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</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
</tr> </tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Type for HostPath Volume Defaults to "" More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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"><a href="#_v1_hostpathtype">v1.HostPathType</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@ -3941,6 +3941,10 @@ Examples:<br>
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_hostpathtype">v1.HostPathType</h3>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_initializers">v1.Initializers</h3> <h3 id="_v1_initializers">v1.Initializers</h3>
@ -4924,11 +4928,18 @@ Examples:<br>
<tbody> <tbody>
<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</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
</tr> </tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Type for HostPath Volume Defaults to "" More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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"><a href="#_v1_hostpathtype">v1.HostPathType</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@ -3838,6 +3838,10 @@ Examples:<br>
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_hostpathtype">v1.HostPathType</h3>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_initializers">v1.Initializers</h3> <h3 id="_v1_initializers">v1.Initializers</h3>
@ -4780,11 +4784,18 @@ Examples:<br>
<tbody> <tbody>
<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</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
</tr> </tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Type for HostPath Volume Defaults to "" More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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"><a href="#_v1_hostpathtype">v1.HostPathType</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@ -5271,6 +5271,10 @@ Examples:<br>
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_hostpathtype">v1.HostPathType</h3>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1beta1_fstype">v1beta1.FSType</h3> <h3 id="_v1beta1_fstype">v1beta1.FSType</h3>
@ -6751,11 +6755,18 @@ Both these may change in the future. Incoming requests are matched against the h
<tbody> <tbody>
<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</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
</tr> </tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Type for HostPath Volume Defaults to "" More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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"><a href="#_v1_hostpathtype">v1.HostPathType</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@ -680,6 +680,10 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_hostpathtype">v1.HostPathType</h3>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_preconditions">v1.Preconditions</h3> <h3 id="_v1_preconditions">v1.Preconditions</h3>
@ -1997,11 +2001,18 @@ When an object is created, the system will populate this list with the current s
<tbody> <tbody>
<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</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
</tr> </tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Type for HostPath Volume Defaults to "" More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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"><a href="#_v1_hostpathtype">v1.HostPathType</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody> </tbody>
</table> </table>
@ -3014,54 +3025,6 @@ When an object is created, the system will populate this list with the current s
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_keytopath">v1.KeyToPath</h3>
<div class="paragraph">
<p>Maps a string key to a path within a volume.</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">key</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The key to project.</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">The relative path of the file to map the key to. May not be an absolute path. May not contain the path element <em>..</em>. May not start with the string <em>..</em>.</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">mode</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.</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">integer (int32)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_azurediskvolumesource">v1.AzureDiskVolumeSource</h3> <h3 id="_v1_azurediskvolumesource">v1.AzureDiskVolumeSource</h3>
@ -3131,6 +3094,54 @@ When an object is created, the system will populate this list with the current s
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_keytopath">v1.KeyToPath</h3>
<div class="paragraph">
<p>Maps a string key to a path within a volume.</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">key</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The key to project.</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">The relative path of the file to map the key to. May not be an absolute path. May not contain the path element <em>..</em>. May not start with the string <em>..</em>.</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">mode</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.</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">integer (int32)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_vspherevirtualdiskvolumesource">v1.VsphereVirtualDiskVolumeSource</h3> <h3 id="_v1_vspherevirtualdiskvolumesource">v1.VsphereVirtualDiskVolumeSource</h3>

View File

@ -3863,6 +3863,54 @@ The resulting set of endpoints can be viewed as:<br>
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_keytopath">v1.KeyToPath</h3>
<div class="paragraph">
<p>Maps a string key to a path within a volume.</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">key</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The key to project.</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">The relative path of the file to map the key to. May not be an absolute path. May not contain the path element <em>..</em>. May not start with the string <em>..</em>.</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">mode</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.</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">integer (int32)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_azurediskvolumesource">v1.AzureDiskVolumeSource</h3> <h3 id="_v1_azurediskvolumesource">v1.AzureDiskVolumeSource</h3>
@ -3932,54 +3980,6 @@ The resulting set of endpoints can be viewed as:<br>
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_keytopath">v1.KeyToPath</h3>
<div class="paragraph">
<p>Maps a string key to a path within a volume.</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">key</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The key to project.</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">The relative path of the file to map the key to. May not be an absolute path. May not contain the path element <em>..</em>. May not start with the string <em>..</em>.</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">mode</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.</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">integer (int32)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_service">v1.Service</h3> <h3 id="_v1_service">v1.Service</h3>
@ -6375,6 +6375,10 @@ Examples:<br>
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_hostpathtype">v1.HostPathType</h3>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_initializers">v1.Initializers</h3> <h3 id="_v1_initializers">v1.Initializers</h3>
@ -8031,11 +8035,18 @@ Examples:<br>
<tbody> <tbody>
<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</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
</tr> </tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Type for HostPath Volume Defaults to "" More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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"><a href="#_v1_hostpathtype">v1.HostPathType</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@ -10605,7 +10605,11 @@
], ],
"properties": { "properties": {
"path": { "path": {
"description": "Path of the directory on the host. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath", "description": "Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath",
"type": "string"
},
"type": {
"description": "Type for HostPath Volume Defaults to \"\" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath",
"type": "string" "type": "string"
} }
} }

View File

@ -5186,10 +5186,18 @@
"properties": { "properties": {
"path": { "path": {
"type": "string", "type": "string",
"description": "Path of the directory on the host. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath" "description": "Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
},
"type": {
"$ref": "v1.HostPathType",
"description": "Type for HostPath Volume Defaults to \"\" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath"
} }
} }
}, },
"v1.HostPathType": {
"id": "v1.HostPathType",
"properties": {}
},
"v1.EmptyDirVolumeSource": { "v1.EmptyDirVolumeSource": {
"id": "v1.EmptyDirVolumeSource", "id": "v1.EmptyDirVolumeSource",
"description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.", "description": "Represents an empty directory for a pod. Empty directory volumes support ownership management and SELinux relabeling.",

View File

@ -4875,6 +4875,10 @@ Examples:<br>
</tbody> </tbody>
</table> </table>
</div>
<div class="sect2">
<h3 id="_v1_hostpathtype">v1.HostPathType</h3>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_v1_initializers">v1.Initializers</h3> <h3 id="_v1_initializers">v1.Initializers</h3>
@ -6234,11 +6238,18 @@ Both these may change in the future. Incoming requests are matched against the h
<tbody> <tbody>
<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</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</a></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>
</tr> </tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Type for HostPath Volume Defaults to "" More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#hostpath">https://kubernetes.io/docs/concepts/storage/volumes#hostpath</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"><a href="#_v1_hostpathtype">v1.HostPathType</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@ -355,6 +355,15 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
r.Keyring = "/etc/ceph/keyring" r.Keyring = "/etc/ceph/keyring"
} }
}, },
func(obj *api.HostPathVolumeSource, c fuzz.Continue) {
c.FuzzNoCustom(obj)
types := []api.HostPathType{api.HostPathUnset, api.HostPathDirectoryOrCreate, api.HostPathDirectory,
api.HostPathFileOrCreate, api.HostPathFile, api.HostPathSocket, api.HostPathCharDev, api.HostPathBlockDev}
typeVol := types[c.Rand.Intn(len(types))]
if obj.Path != "" && obj.Type == nil {
obj.Type = &typeVol
}
},
func(pv *api.PersistentVolume, c fuzz.Continue) { func(pv *api.PersistentVolume, c fuzz.Continue) {
c.FuzzNoCustom(pv) // fuzz self without calling this function again c.FuzzNoCustom(pv) // fuzz self without calling this function again
types := []api.PersistentVolumePhase{api.VolumeAvailable, api.VolumePending, api.VolumeBound, api.VolumeReleased, api.VolumeFailed} types := []api.PersistentVolumePhase{api.VolumeAvailable, api.VolumePending, api.VolumeBound, api.VolumeReleased, api.VolumeFailed}

View File

@ -597,10 +597,36 @@ const (
ClaimLost PersistentVolumeClaimPhase = "Lost" ClaimLost PersistentVolumeClaimPhase = "Lost"
) )
type HostPathType string
const (
// For backwards compatible, leave it empty if unset
HostPathUnset HostPathType = ""
// If nothing exists at the given path, an empty directory will be created there
// as needed with file mode 0755, having the same group and ownership with Kubelet.
HostPathDirectoryOrCreate HostPathType = "DirectoryOrCreate"
// A directory must exist at the given path
HostPathDirectory HostPathType = "Directory"
// If nothing exists at the given path, an empty file will be created there
// as needed with file mode 0644, having the same group and ownership with Kubelet.
HostPathFileOrCreate HostPathType = "FileOrCreate"
// A file must exist at the given path
HostPathFile HostPathType = "File"
// A UNIX socket must exist at the given path
HostPathSocket HostPathType = "Socket"
// A character device must exist at the given path
HostPathCharDev HostPathType = "CharDevice"
// A block device must exist at the given path
HostPathBlockDev HostPathType = "BlockDevice"
)
// Represents a host path mapped into a pod. // Represents a host path mapped into a pod.
// Host path volumes do not support ownership management or SELinux relabeling. // Host path volumes do not support ownership management or SELinux relabeling.
type HostPathVolumeSource struct { type HostPathVolumeSource struct {
// If the path is a symlink, it will follow the link to the real path.
Path string Path string
// Defaults to ""
Type *HostPathType
} }
// Represents an empty directory for a pod. // Represents an empty directory for a pod.

View File

@ -369,3 +369,10 @@ func SetDefaults_ScaleIOVolumeSource(obj *v1.ScaleIOVolumeSource) {
obj.FSType = "xfs" obj.FSType = "xfs"
} }
} }
func SetDefaults_HostPathVolumeSource(obj *v1.HostPathVolumeSource) {
typeVol := v1.HostPathUnset
if obj.Type == nil {
obj.Type = &typeVol
}
}

View File

@ -1277,3 +1277,25 @@ func TestSetDefaultSchedulerName(t *testing.T) {
t.Errorf("Expected scheduler name: %+v\ngot: %+v\n", v1.DefaultSchedulerName, output.Spec.SchedulerName) t.Errorf("Expected scheduler name: %+v\ngot: %+v\n", v1.DefaultSchedulerName, output.Spec.SchedulerName)
} }
} }
func TestSetDefaultHostPathVolumeSource(t *testing.T) {
s := v1.PodSpec{}
s.Volumes = []v1.Volume{
{
VolumeSource: v1.VolumeSource{
HostPath: &v1.HostPathVolumeSource{Path: "foo"},
},
},
}
pod := &v1.Pod{
Spec: s,
}
output := roundTrip(t, runtime.Object(pod))
pod2 := output.(*v1.Pod)
defaultType := pod2.Spec.Volumes[0].VolumeSource.HostPath.Type
expectedType := v1.HostPathUnset
if defaultType == nil || *defaultType != expectedType {
t.Errorf("Expected v1.HostPathVolumeSource default type %v, got %v", expectedType, defaultType)
}
}

View File

@ -1841,6 +1841,7 @@ func Convert_api_HostAlias_To_v1_HostAlias(in *api.HostAlias, out *v1.HostAlias,
func autoConvert_v1_HostPathVolumeSource_To_api_HostPathVolumeSource(in *v1.HostPathVolumeSource, out *api.HostPathVolumeSource, s conversion.Scope) error { func autoConvert_v1_HostPathVolumeSource_To_api_HostPathVolumeSource(in *v1.HostPathVolumeSource, out *api.HostPathVolumeSource, s conversion.Scope) error {
out.Path = in.Path out.Path = in.Path
out.Type = (*api.HostPathType)(unsafe.Pointer(in.Type))
return nil return nil
} }
@ -1851,6 +1852,7 @@ func Convert_v1_HostPathVolumeSource_To_api_HostPathVolumeSource(in *v1.HostPath
func autoConvert_api_HostPathVolumeSource_To_v1_HostPathVolumeSource(in *api.HostPathVolumeSource, out *v1.HostPathVolumeSource, s conversion.Scope) error { func autoConvert_api_HostPathVolumeSource_To_v1_HostPathVolumeSource(in *api.HostPathVolumeSource, out *v1.HostPathVolumeSource, s conversion.Scope) error {
out.Path = in.Path out.Path = in.Path
out.Type = (*v1.HostPathType)(unsafe.Pointer(in.Type))
return nil return nil
} }

View File

@ -133,6 +133,9 @@ func SetObjectDefaults_NodeList(in *v1.NodeList) {
func SetObjectDefaults_PersistentVolume(in *v1.PersistentVolume) { func SetObjectDefaults_PersistentVolume(in *v1.PersistentVolume) {
SetDefaults_PersistentVolume(in) SetDefaults_PersistentVolume(in)
SetDefaults_ResourceList(&in.Spec.Capacity) SetDefaults_ResourceList(&in.Spec.Capacity)
if in.Spec.PersistentVolumeSource.HostPath != nil {
SetDefaults_HostPathVolumeSource(in.Spec.PersistentVolumeSource.HostPath)
}
if in.Spec.PersistentVolumeSource.RBD != nil { if in.Spec.PersistentVolumeSource.RBD != nil {
SetDefaults_RBDVolumeSource(in.Spec.PersistentVolumeSource.RBD) SetDefaults_RBDVolumeSource(in.Spec.PersistentVolumeSource.RBD)
} }
@ -174,6 +177,9 @@ func SetObjectDefaults_Pod(in *v1.Pod) {
for i := range in.Spec.Volumes { for i := range in.Spec.Volumes {
a := &in.Spec.Volumes[i] a := &in.Spec.Volumes[i]
SetDefaults_Volume(a) SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }
@ -322,6 +328,9 @@ func SetObjectDefaults_PodTemplate(in *v1.PodTemplate) {
for i := range in.Template.Spec.Volumes { for i := range in.Template.Spec.Volumes {
a := &in.Template.Spec.Volumes[i] a := &in.Template.Spec.Volumes[i]
SetDefaults_Volume(a) SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }
@ -464,6 +473,9 @@ func SetObjectDefaults_ReplicationController(in *v1.ReplicationController) {
for i := range in.Spec.Template.Spec.Volumes { for i := range in.Spec.Template.Spec.Volumes {
a := &in.Spec.Template.Spec.Volumes[i] a := &in.Spec.Template.Spec.Volumes[i]
SetDefaults_Volume(a) SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }

View File

@ -623,6 +623,7 @@ func validateHostPathVolumeSource(hostPath *api.HostPathVolumeSource, fldPath *f
} }
allErrs = append(allErrs, validatePathNoBacksteps(hostPath.Path, fldPath.Child("path"))...) allErrs = append(allErrs, validatePathNoBacksteps(hostPath.Path, fldPath.Child("path"))...)
allErrs = append(allErrs, validateHostPathType(hostPath.Type, fldPath.Child("type"))...)
return allErrs return allErrs
} }
@ -974,6 +975,26 @@ func validateProjectedVolumeSource(projection *api.ProjectedVolumeSource, fldPat
return allErrs return allErrs
} }
var supportedHostPathTypes = sets.NewString(
string(api.HostPathUnset),
string(api.HostPathDirectoryOrCreate),
string(api.HostPathDirectory),
string(api.HostPathFileOrCreate),
string(api.HostPathFile),
string(api.HostPathSocket),
string(api.HostPathCharDev),
string(api.HostPathBlockDev))
func validateHostPathType(hostPathType *api.HostPathType, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if !supportedHostPathTypes.Has(string(*hostPathType)) {
allErrs = append(allErrs, field.NotSupported(fldPath, hostPathType, supportedHostPathTypes.List()))
}
return allErrs
}
// This validate will make sure targetPath: // This validate will make sure targetPath:
// 1. is not abs path // 1. is not abs path
// 2. does not have any element which is ".." // 2. does not have any element which is ".."

View File

@ -43,6 +43,12 @@ const (
envVarNameErrMsg = "a valid environment variable name must consist of" envVarNameErrMsg = "a valid environment variable name must consist of"
) )
func newHostPathType(pathType string) *api.HostPathType {
hostPathType := new(api.HostPathType)
*hostPathType = api.HostPathType(pathType)
return hostPathType
}
func testVolume(name string, namespace string, spec api.PersistentVolumeSpec) *api.PersistentVolume { func testVolume(name string, namespace string, spec api.PersistentVolumeSpec) *api.PersistentVolume {
objMeta := metav1.ObjectMeta{Name: name} objMeta := metav1.ObjectMeta{Name: name}
if namespace != "" { if namespace != "" {
@ -86,7 +92,10 @@ func TestValidatePersistentVolumes(t *testing.T) {
}, },
AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
PersistentVolumeSource: api.PersistentVolumeSource{ PersistentVolumeSource: api.PersistentVolumeSource{
HostPath: &api.HostPathVolumeSource{Path: "/foo"}, HostPath: &api.HostPathVolumeSource{
Path: "/foo",
Type: newHostPathType(string(api.HostPathDirectory)),
},
}, },
StorageClassName: "valid", StorageClassName: "valid",
}), }),
@ -99,7 +108,10 @@ func TestValidatePersistentVolumes(t *testing.T) {
}, },
AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
PersistentVolumeSource: api.PersistentVolumeSource{ PersistentVolumeSource: api.PersistentVolumeSource{
HostPath: &api.HostPathVolumeSource{Path: "/foo"}, HostPath: &api.HostPathVolumeSource{
Path: "/foo",
Type: newHostPathType(string(api.HostPathDirectory)),
},
}, },
PersistentVolumeReclaimPolicy: api.PersistentVolumeReclaimRetain, PersistentVolumeReclaimPolicy: api.PersistentVolumeReclaimRetain,
}), }),
@ -112,7 +124,10 @@ func TestValidatePersistentVolumes(t *testing.T) {
}, },
AccessModes: []api.PersistentVolumeAccessMode{"fakemode"}, AccessModes: []api.PersistentVolumeAccessMode{"fakemode"},
PersistentVolumeSource: api.PersistentVolumeSource{ PersistentVolumeSource: api.PersistentVolumeSource{
HostPath: &api.HostPathVolumeSource{Path: "/foo"}, HostPath: &api.HostPathVolumeSource{
Path: "/foo",
Type: newHostPathType(string(api.HostPathDirectory)),
},
}, },
}), }),
}, },
@ -124,7 +139,10 @@ func TestValidatePersistentVolumes(t *testing.T) {
}, },
AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
PersistentVolumeSource: api.PersistentVolumeSource{ PersistentVolumeSource: api.PersistentVolumeSource{
HostPath: &api.HostPathVolumeSource{Path: "/foo"}, HostPath: &api.HostPathVolumeSource{
Path: "/foo",
Type: newHostPathType(string(api.HostPathDirectory)),
},
}, },
PersistentVolumeReclaimPolicy: "fakeReclaimPolicy", PersistentVolumeReclaimPolicy: "fakeReclaimPolicy",
}), }),
@ -137,7 +155,10 @@ func TestValidatePersistentVolumes(t *testing.T) {
}, },
AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
PersistentVolumeSource: api.PersistentVolumeSource{ PersistentVolumeSource: api.PersistentVolumeSource{
HostPath: &api.HostPathVolumeSource{Path: "/foo"}, HostPath: &api.HostPathVolumeSource{
Path: "/foo",
Type: newHostPathType(string(api.HostPathDirectory)),
},
}, },
}), }),
}, },
@ -149,7 +170,10 @@ func TestValidatePersistentVolumes(t *testing.T) {
}, },
AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
PersistentVolumeSource: api.PersistentVolumeSource{ PersistentVolumeSource: api.PersistentVolumeSource{
HostPath: &api.HostPathVolumeSource{Path: "/foo"}, HostPath: &api.HostPathVolumeSource{
Path: "/foo",
Type: newHostPathType(string(api.HostPathDirectory)),
},
}, },
}), }),
}, },
@ -173,7 +197,10 @@ func TestValidatePersistentVolumes(t *testing.T) {
api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), api.ResourceName(api.ResourceStorage): resource.MustParse("10G"),
}, },
PersistentVolumeSource: api.PersistentVolumeSource{ PersistentVolumeSource: api.PersistentVolumeSource{
HostPath: &api.HostPathVolumeSource{Path: "/foo"}, HostPath: &api.HostPathVolumeSource{
Path: "/foo",
Type: newHostPathType(string(api.HostPathDirectory)),
},
}, },
}), }),
}, },
@ -184,7 +211,10 @@ func TestValidatePersistentVolumes(t *testing.T) {
api.ResourceName(api.ResourceStorage): resource.MustParse("5G"), api.ResourceName(api.ResourceStorage): resource.MustParse("5G"),
}, },
PersistentVolumeSource: api.PersistentVolumeSource{ PersistentVolumeSource: api.PersistentVolumeSource{
HostPath: &api.HostPathVolumeSource{Path: "/foo"}, HostPath: &api.HostPathVolumeSource{
Path: "/foo",
Type: newHostPathType(string(api.HostPathDirectory)),
},
GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{PDName: "foo", FSType: "ext4"}, GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{PDName: "foo", FSType: "ext4"},
}, },
}), }),
@ -197,7 +227,10 @@ func TestValidatePersistentVolumes(t *testing.T) {
}, },
AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
PersistentVolumeSource: api.PersistentVolumeSource{ PersistentVolumeSource: api.PersistentVolumeSource{
HostPath: &api.HostPathVolumeSource{Path: "/"}, HostPath: &api.HostPathVolumeSource{
Path: "/",
Type: newHostPathType(string(api.HostPathDirectory)),
},
}, },
PersistentVolumeReclaimPolicy: api.PersistentVolumeReclaimRecycle, PersistentVolumeReclaimPolicy: api.PersistentVolumeReclaimRecycle,
}), }),
@ -210,7 +243,10 @@ func TestValidatePersistentVolumes(t *testing.T) {
}, },
AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
PersistentVolumeSource: api.PersistentVolumeSource{ PersistentVolumeSource: api.PersistentVolumeSource{
HostPath: &api.HostPathVolumeSource{Path: "/a/.."}, HostPath: &api.HostPathVolumeSource{
Path: "/a/..",
Type: newHostPathType(string(api.HostPathDirectory)),
},
}, },
PersistentVolumeReclaimPolicy: api.PersistentVolumeReclaimRecycle, PersistentVolumeReclaimPolicy: api.PersistentVolumeReclaimRecycle,
}), }),
@ -223,7 +259,10 @@ func TestValidatePersistentVolumes(t *testing.T) {
}, },
AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
PersistentVolumeSource: api.PersistentVolumeSource{ PersistentVolumeSource: api.PersistentVolumeSource{
HostPath: &api.HostPathVolumeSource{Path: "/foo"}, HostPath: &api.HostPathVolumeSource{
Path: "/foo",
Type: newHostPathType(string(api.HostPathDirectory)),
},
}, },
StorageClassName: "-invalid-", StorageClassName: "-invalid-",
}), }),
@ -272,7 +311,10 @@ func TestValidatePersistentVolumes(t *testing.T) {
}, },
AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
PersistentVolumeSource: api.PersistentVolumeSource{ PersistentVolumeSource: api.PersistentVolumeSource{
HostPath: &api.HostPathVolumeSource{Path: "/foo/.."}, HostPath: &api.HostPathVolumeSource{
Path: "/foo/..",
Type: newHostPathType(string(api.HostPathDirectory)),
},
}, },
StorageClassName: "backstep-hostpath", StorageClassName: "backstep-hostpath",
}), }),
@ -1109,6 +1151,7 @@ func TestValidateVolumes(t *testing.T) {
EmptyDir: &api.EmptyDirVolumeSource{}, EmptyDir: &api.EmptyDirVolumeSource{},
HostPath: &api.HostPathVolumeSource{ HostPath: &api.HostPathVolumeSource{
Path: "/mnt/path", Path: "/mnt/path",
Type: newHostPathType(string(api.HostPathDirectory)),
}, },
}, },
}, },
@ -1116,7 +1159,20 @@ func TestValidateVolumes(t *testing.T) {
errfield: "hostPath", errfield: "hostPath",
errdetail: "may not specify more than 1 volume", errdetail: "may not specify more than 1 volume",
}, },
// HostPath // HostPath Default
{
name: "default HostPath",
vol: api.Volume{
Name: "hostpath",
VolumeSource: api.VolumeSource{
HostPath: &api.HostPathVolumeSource{
Path: "/mnt/path",
Type: newHostPathType(string(api.HostPathDirectory)),
},
},
},
},
// HostPath Supported
{ {
name: "valid HostPath", name: "valid HostPath",
vol: api.Volume{ vol: api.Volume{
@ -1124,10 +1180,26 @@ func TestValidateVolumes(t *testing.T) {
VolumeSource: api.VolumeSource{ VolumeSource: api.VolumeSource{
HostPath: &api.HostPathVolumeSource{ HostPath: &api.HostPathVolumeSource{
Path: "/mnt/path", Path: "/mnt/path",
Type: newHostPathType(string(api.HostPathSocket)),
}, },
}, },
}, },
}, },
// HostPath Invalid
{
name: "invalid HostPath",
vol: api.Volume{
Name: "hostpath",
VolumeSource: api.VolumeSource{
HostPath: &api.HostPathVolumeSource{
Path: "/mnt/path",
Type: newHostPathType("invalid"),
},
},
},
errtype: field.ErrorTypeNotSupported,
errfield: "type",
},
{ {
name: "invalid HostPath backsteps", name: "invalid HostPath backsteps",
vol: api.Volume{ vol: api.Volume{
@ -1135,6 +1207,7 @@ func TestValidateVolumes(t *testing.T) {
VolumeSource: api.VolumeSource{ VolumeSource: api.VolumeSource{
HostPath: &api.HostPathVolumeSource{ HostPath: &api.HostPathVolumeSource{
Path: "/mnt/path/..", Path: "/mnt/path/..",
Type: newHostPathType(string(api.HostPathDirectory)),
}, },
}, },
}, },

View File

@ -2303,6 +2303,15 @@ func (in *HostAlias) DeepCopy() *HostAlias {
// 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 *HostPathVolumeSource) DeepCopyInto(out *HostPathVolumeSource) { func (in *HostPathVolumeSource) DeepCopyInto(out *HostPathVolumeSource) {
*out = *in *out = *in
if in.Type != nil {
in, out := &in.Type, &out.Type
if *in == nil {
*out = nil
} else {
*out = new(HostPathType)
**out = **in
}
}
return return
} }
@ -3572,7 +3581,7 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) {
*out = nil *out = nil
} else { } else {
*out = new(HostPathVolumeSource) *out = new(HostPathVolumeSource)
**out = **in (*in).DeepCopyInto(*out)
} }
} }
if in.Glusterfs != nil { if in.Glusterfs != nil {
@ -5823,7 +5832,7 @@ func (in *VolumeSource) DeepCopyInto(out *VolumeSource) {
*out = nil *out = nil
} else { } else {
*out = new(HostPathVolumeSource) *out = new(HostPathVolumeSource)
**out = **in (*in).DeepCopyInto(*out)
} }
} }
if in.EmptyDir != nil { if in.EmptyDir != nil {

View File

@ -43,6 +43,9 @@ func SetObjectDefaults_Deployment(in *v1beta1.Deployment) {
for i := range in.Spec.Template.Spec.Volumes { for i := range in.Spec.Template.Spec.Volumes {
a := &in.Spec.Template.Spec.Volumes[i] a := &in.Spec.Template.Spec.Volumes[i]
v1.SetDefaults_Volume(a) v1.SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
v1.SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }
@ -184,6 +187,9 @@ func SetObjectDefaults_StatefulSet(in *v1beta1.StatefulSet) {
for i := range in.Spec.Template.Spec.Volumes { for i := range in.Spec.Template.Spec.Volumes {
a := &in.Spec.Template.Spec.Volumes[i] a := &in.Spec.Template.Spec.Volumes[i]
v1.SetDefaults_Volume(a) v1.SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
v1.SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }

View File

@ -47,6 +47,9 @@ func SetObjectDefaults_DaemonSet(in *v1beta2.DaemonSet) {
for i := range in.Spec.Template.Spec.Volumes { for i := range in.Spec.Template.Spec.Volumes {
a := &in.Spec.Template.Spec.Volumes[i] a := &in.Spec.Template.Spec.Volumes[i]
v1.SetDefaults_Volume(a) v1.SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
v1.SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }
@ -188,6 +191,9 @@ func SetObjectDefaults_Deployment(in *v1beta2.Deployment) {
for i := range in.Spec.Template.Spec.Volumes { for i := range in.Spec.Template.Spec.Volumes {
a := &in.Spec.Template.Spec.Volumes[i] a := &in.Spec.Template.Spec.Volumes[i]
v1.SetDefaults_Volume(a) v1.SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
v1.SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }
@ -329,6 +335,9 @@ func SetObjectDefaults_ReplicaSet(in *v1beta2.ReplicaSet) {
for i := range in.Spec.Template.Spec.Volumes { for i := range in.Spec.Template.Spec.Volumes {
a := &in.Spec.Template.Spec.Volumes[i] a := &in.Spec.Template.Spec.Volumes[i]
v1.SetDefaults_Volume(a) v1.SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
v1.SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }
@ -470,6 +479,9 @@ func SetObjectDefaults_StatefulSet(in *v1beta2.StatefulSet) {
for i := range in.Spec.Template.Spec.Volumes { for i := range in.Spec.Template.Spec.Volumes {
a := &in.Spec.Template.Spec.Volumes[i] a := &in.Spec.Template.Spec.Volumes[i]
v1.SetDefaults_Volume(a) v1.SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
v1.SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }

View File

@ -41,6 +41,9 @@ func SetObjectDefaults_Job(in *v1.Job) {
for i := range in.Spec.Template.Spec.Volumes { for i := range in.Spec.Template.Spec.Volumes {
a := &in.Spec.Template.Spec.Volumes[i] a := &in.Spec.Template.Spec.Volumes[i]
api_v1.SetDefaults_Volume(a) api_v1.SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
api_v1.SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
api_v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) api_v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }

View File

@ -42,6 +42,9 @@ func SetObjectDefaults_CronJob(in *v1beta1.CronJob) {
for i := range in.Spec.JobTemplate.Spec.Template.Spec.Volumes { for i := range in.Spec.JobTemplate.Spec.Template.Spec.Volumes {
a := &in.Spec.JobTemplate.Spec.Template.Spec.Volumes[i] a := &in.Spec.JobTemplate.Spec.Template.Spec.Volumes[i]
v1.SetDefaults_Volume(a) v1.SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
v1.SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }
@ -182,6 +185,9 @@ func SetObjectDefaults_JobTemplate(in *v1beta1.JobTemplate) {
for i := range in.Template.Spec.Template.Spec.Volumes { for i := range in.Template.Spec.Template.Spec.Volumes {
a := &in.Template.Spec.Template.Spec.Volumes[i] a := &in.Template.Spec.Template.Spec.Volumes[i]
v1.SetDefaults_Volume(a) v1.SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
v1.SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }

View File

@ -42,6 +42,9 @@ func SetObjectDefaults_CronJob(in *v2alpha1.CronJob) {
for i := range in.Spec.JobTemplate.Spec.Template.Spec.Volumes { for i := range in.Spec.JobTemplate.Spec.Template.Spec.Volumes {
a := &in.Spec.JobTemplate.Spec.Template.Spec.Volumes[i] a := &in.Spec.JobTemplate.Spec.Template.Spec.Volumes[i]
v1.SetDefaults_Volume(a) v1.SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
v1.SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }
@ -182,6 +185,9 @@ func SetObjectDefaults_JobTemplate(in *v2alpha1.JobTemplate) {
for i := range in.Template.Spec.Template.Spec.Volumes { for i := range in.Template.Spec.Template.Spec.Volumes {
a := &in.Template.Spec.Template.Spec.Volumes[i] a := &in.Template.Spec.Template.Spec.Volumes[i]
v1.SetDefaults_Volume(a) v1.SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
v1.SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }

View File

@ -47,6 +47,9 @@ func SetObjectDefaults_DaemonSet(in *v1beta1.DaemonSet) {
for i := range in.Spec.Template.Spec.Volumes { for i := range in.Spec.Template.Spec.Volumes {
a := &in.Spec.Template.Spec.Volumes[i] a := &in.Spec.Template.Spec.Volumes[i]
v1.SetDefaults_Volume(a) v1.SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
v1.SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }
@ -188,6 +191,9 @@ func SetObjectDefaults_Deployment(in *v1beta1.Deployment) {
for i := range in.Spec.Template.Spec.Volumes { for i := range in.Spec.Template.Spec.Volumes {
a := &in.Spec.Template.Spec.Volumes[i] a := &in.Spec.Template.Spec.Volumes[i]
v1.SetDefaults_Volume(a) v1.SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
v1.SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }
@ -340,6 +346,9 @@ func SetObjectDefaults_ReplicaSet(in *v1beta1.ReplicaSet) {
for i := range in.Spec.Template.Spec.Volumes { for i := range in.Spec.Template.Spec.Volumes {
a := &in.Spec.Template.Spec.Volumes[i] a := &in.Spec.Template.Spec.Volumes[i]
v1.SetDefaults_Volume(a) v1.SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
v1.SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }

View File

@ -47,6 +47,9 @@ func SetObjectDefaults_PodPreset(in *v1alpha1.PodPreset) {
for i := range in.Spec.Volumes { for i := range in.Spec.Volumes {
a := &in.Spec.Volumes[i] a := &in.Spec.Volumes[i]
v1.SetDefaults_Volume(a) v1.SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
v1.SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil { if a.VolumeSource.Secret != nil {
v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret) v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
} }

View File

@ -69,6 +69,7 @@ func (kl *Kubelet) newVolumeMounterFromPlugins(spec *volume.Spec, pod *v1.Pod, o
if err != nil { if err != nil {
return nil, fmt.Errorf("can't use volume plugins for %s: %v", spec.Name(), err) return nil, fmt.Errorf("can't use volume plugins for %s: %v", spec.Name(), err)
} }
opts.Containerized = kl.kubeletConfiguration.Containerized
physicalMounter, err := plugin.NewMounter(spec, pod, opts) physicalMounter, err := plugin.NewMounter(spec, pod, opts)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to instantiate mounter for volume: %s using plugin: %s with a root cause: %v", spec.Name(), plugin.GetPluginName(), err) return nil, fmt.Errorf("failed to instantiate mounter for volume: %s using plugin: %s with a root cause: %v", spec.Name(), plugin.GetPluginName(), err)

View File

@ -46,6 +46,12 @@ func newStorage(t *testing.T) (*REST, *StatusREST, *etcdtesting.EtcdTestServer)
return persistentVolumeStorage, statusStorage, server return persistentVolumeStorage, statusStorage, server
} }
func newHostPathType(pathType string) *api.HostPathType {
hostPathType := new(api.HostPathType)
*hostPathType = api.HostPathType(pathType)
return hostPathType
}
func validNewPersistentVolume(name string) *api.PersistentVolume { func validNewPersistentVolume(name string) *api.PersistentVolume {
pv := &api.PersistentVolume{ pv := &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
@ -57,7 +63,7 @@ func validNewPersistentVolume(name string) *api.PersistentVolume {
}, },
AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
PersistentVolumeSource: api.PersistentVolumeSource{ PersistentVolumeSource: api.PersistentVolumeSource{
HostPath: &api.HostPathVolumeSource{Path: "/foo"}, HostPath: &api.HostPathVolumeSource{Path: "/foo", Type: newHostPathType(string(api.HostPathDirectoryOrCreate))},
}, },
PersistentVolumeReclaimPolicy: api.PersistentVolumeReclaimRetain, PersistentVolumeReclaimPolicy: api.PersistentVolumeReclaimRetain,
}, },

View File

@ -11,7 +11,20 @@ go_library(
srcs = [ srcs = [
"doc.go", "doc.go",
"host_path.go", "host_path.go",
], "nsenter_unsupported.go",
] + select({
"@io_bazel_rules_go//go/platform:darwin_amd64": [
"host_path_unix.go",
],
"@io_bazel_rules_go//go/platform:linux_amd64": [
"host_path_unix.go",
"nsenter.go",
],
"@io_bazel_rules_go//go/platform:windows_amd64": [
"host_path_windows.go",
],
"//conditions:default": [],
}),
deps = [ deps = [
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util/volumehelper:go_default_library", "//pkg/volume/util/volumehelper:go_default_library",
@ -20,7 +33,12 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
], ] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"//conditions:default": [],
}),
) )
go_test( go_test(

View File

@ -99,14 +99,15 @@ func (plugin *hostPathPlugin) GetAccessModes() []v1.PersistentVolumeAccessMode {
} }
} }
func (plugin *hostPathPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.Mounter, error) { func (plugin *hostPathPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts volume.VolumeOptions) (volume.Mounter, error) {
hostPathVolumeSource, readOnly, err := getVolumeSource(spec) hostPathVolumeSource, readOnly, err := getVolumeSource(spec)
if err != nil { if err != nil {
return nil, err return nil, err
} }
path := hostPathVolumeSource.Path
return &hostPathMounter{ return &hostPathMounter{
hostPath: &hostPath{path: hostPathVolumeSource.Path}, hostPath: &hostPath{path: path, pathType: hostPathVolumeSource.Type, containerized: opts.Containerized},
readOnly: readOnly, readOnly: readOnly,
}, nil }, nil
} }
@ -175,7 +176,9 @@ func newProvisioner(options volume.VolumeOptions, host volume.VolumeHost, plugin
// HostPath volumes represent a bare host file or directory mount. // HostPath volumes represent a bare host file or directory mount.
// The direct at the specified path will be directly exposed to the container. // The direct at the specified path will be directly exposed to the container.
type hostPath struct { type hostPath struct {
path string path string
pathType *v1.HostPathType
containerized bool
volume.MetricsNil volume.MetricsNil
} }
@ -211,7 +214,11 @@ func (b *hostPathMounter) SetUp(fsGroup *int64) error {
if err != nil { if err != nil {
return fmt.Errorf("invalid HostPath `%s`: %v", b.GetPath(), err) return fmt.Errorf("invalid HostPath `%s`: %v", b.GetPath(), err)
} }
return nil
if *b.pathType == v1.HostPathUnset {
return nil
}
return checkType(b.GetPath(), b.pathType, b.containerized)
} }
// SetUpAt does not make sense for host paths - probably programmer error. // SetUpAt does not make sense for host paths - probably programmer error.
@ -314,3 +321,182 @@ func getVolumeSource(spec *volume.Spec) (*v1.HostPathVolumeSource, bool, error)
return nil, false, fmt.Errorf("Spec does not reference an HostPath volume type") return nil, false, fmt.Errorf("Spec does not reference an HostPath volume type")
} }
type hostPathTypeChecker interface {
Exists() bool
IsFile() bool
MakeFile() error
IsDir() bool
MakeDir() error
IsBlock() bool
IsChar() bool
IsSocket() bool
GetPath() string
}
type fileTypeChecker interface {
getFileType(fileInfo os.FileInfo) (v1.HostPathType, error)
}
// this is implemented in per-OS files
type defaultFileTypeChecker struct{}
type osFileTypeChecker struct {
path string
exists bool
info os.FileInfo
checker fileTypeChecker
}
func (ftc *osFileTypeChecker) Exists() bool {
return ftc.exists
}
func (ftc *osFileTypeChecker) IsFile() bool {
if !ftc.Exists() {
return false
}
return !ftc.info.IsDir()
}
func (ftc *osFileTypeChecker) MakeFile() error {
f, err := os.OpenFile(ftc.path, os.O_CREATE, os.FileMode(0644))
defer f.Close()
if err != nil {
if !os.IsExist(err) {
return err
}
}
return nil
}
func (ftc *osFileTypeChecker) IsDir() bool {
if !ftc.Exists() {
return false
}
return ftc.info.IsDir()
}
func (ftc *osFileTypeChecker) MakeDir() error {
err := os.MkdirAll(ftc.path, os.FileMode(0755))
if err != nil {
if !os.IsExist(err) {
return err
}
}
return nil
}
func (ftc *osFileTypeChecker) IsBlock() bool {
if !ftc.Exists() {
return false
}
blkDevType, err := ftc.checker.getFileType(ftc.info)
if err != nil {
return false
}
return blkDevType == v1.HostPathBlockDev
}
func (ftc *osFileTypeChecker) IsChar() bool {
if !ftc.Exists() {
return false
}
charDevType, err := ftc.checker.getFileType(ftc.info)
if err != nil {
return false
}
return charDevType == v1.HostPathCharDev
}
func (ftc *osFileTypeChecker) IsSocket() bool {
if !ftc.Exists() {
return false
}
socketType, err := ftc.checker.getFileType(ftc.info)
if err != nil {
return false
}
return socketType == v1.HostPathSocket
}
func (ftc *osFileTypeChecker) GetPath() string {
return ftc.path
}
func newOSFileTypeChecker(path string, checker fileTypeChecker) (hostPathTypeChecker, error) {
ftc := osFileTypeChecker{path: path, checker: checker}
info, err := os.Stat(path)
if err != nil {
ftc.exists = false
if !os.IsNotExist(err) {
return nil, err
}
} else {
ftc.info = info
ftc.exists = true
}
return &ftc, nil
}
func checkType(path string, pathType *v1.HostPathType, containerized bool) error {
var ftc hostPathTypeChecker
var err error
if containerized {
// For a containerized kubelet, use nsenter to run commands in
// the host's mount namespace.
// TODO(dixudx): setns into docker's mount namespace, and then run the exact same go code for checks/setup
ftc, err = newNsenterFileTypeChecker(path)
if err != nil {
return err
}
} else {
ftc, err = newOSFileTypeChecker(path, &defaultFileTypeChecker{})
if err != nil {
return err
}
}
return checkTypeInternal(ftc, pathType)
}
func checkTypeInternal(ftc hostPathTypeChecker, pathType *v1.HostPathType) error {
switch *pathType {
case v1.HostPathDirectoryOrCreate:
if !ftc.Exists() {
return ftc.MakeDir()
}
fallthrough
case v1.HostPathDirectory:
if !ftc.IsDir() {
return fmt.Errorf("hostPath type check failed: %s is not a directory", ftc.GetPath())
}
case v1.HostPathFileOrCreate:
if !ftc.Exists() {
return ftc.MakeFile()
}
fallthrough
case v1.HostPathFile:
if !ftc.IsFile() {
return fmt.Errorf("hostPath type check failed: %s is not a file", ftc.GetPath())
}
case v1.HostPathSocket:
if !ftc.IsSocket() {
return fmt.Errorf("hostPath type check failed: %s is not a socket file", ftc.GetPath())
}
case v1.HostPathCharDev:
if !ftc.IsChar() {
return fmt.Errorf("hostPath type check failed: %s is not a character device", ftc.GetPath())
}
case v1.HostPathBlockDev:
if !ftc.IsBlock() {
return fmt.Errorf("hostPath type check failed: %s is not a block device", ftc.GetPath())
}
default:
return fmt.Errorf("%s is an invalid volume type", *pathType)
}
return nil
}

View File

@ -34,6 +34,21 @@ import (
volumetest "k8s.io/kubernetes/pkg/volume/testing" volumetest "k8s.io/kubernetes/pkg/volume/testing"
) )
func newHostPathType(pathType string) *v1.HostPathType {
hostPathType := new(v1.HostPathType)
*hostPathType = v1.HostPathType(pathType)
return hostPathType
}
func newHostPathTypeList(pathType ...string) []*v1.HostPathType {
typeList := []*v1.HostPathType{}
for _, ele := range pathType {
typeList = append(typeList, newHostPathType(ele))
}
return typeList
}
func TestCanSupport(t *testing.T) { func TestCanSupport(t *testing.T) {
plugMgr := volume.VolumePluginMgr{} plugMgr := volume.VolumePluginMgr{}
plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), volumetest.NewFakeVolumeHost("fake", nil, nil)) plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), volumetest.NewFakeVolumeHost("fake", nil, nil))
@ -108,7 +123,7 @@ func TestDeleter(t *testing.T) {
if err := deleter.Delete(); err != nil { if err := deleter.Delete(); err != nil {
t.Errorf("Mock Recycler expected to return nil but got %s", err) t.Errorf("Mock Recycler expected to return nil but got %s", err)
} }
if exists, _ := utilfile.FileExists("foo"); exists { if exists, _ := utilfile.FileExists(tempPath); exists {
t.Errorf("Temp path expected to be deleted, but was found at %s", tempPath) t.Errorf("Temp path expected to be deleted, but was found at %s", tempPath)
} }
} }
@ -215,11 +230,14 @@ func TestPlugin(t *testing.T) {
if err != nil { if err != nil {
t.Errorf("Can't find the plugin by name") t.Errorf("Can't find the plugin by name")
} }
volPath := "/tmp/vol1"
spec := &v1.Volume{ spec := &v1.Volume{
Name: "vol1", Name: "vol1",
VolumeSource: v1.VolumeSource{HostPath: &v1.HostPathVolumeSource{Path: "/vol1"}}, VolumeSource: v1.VolumeSource{HostPath: &v1.HostPathVolumeSource{Path: volPath, Type: newHostPathType(string(v1.HostPathDirectoryOrCreate))}},
} }
pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}} pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}}
defer os.RemoveAll(volPath)
mounter, err := plug.NewMounter(volume.NewSpecFromVolume(spec), pod, volume.VolumeOptions{}) mounter, err := plug.NewMounter(volume.NewSpecFromVolume(spec), pod, volume.VolumeOptions{})
if err != nil { if err != nil {
t.Errorf("Failed to make a new Mounter: %v", err) t.Errorf("Failed to make a new Mounter: %v", err)
@ -229,7 +247,7 @@ func TestPlugin(t *testing.T) {
} }
path := mounter.GetPath() path := mounter.GetPath()
if path != "/vol1" { if path != volPath {
t.Errorf("Got unexpected path: %s", path) t.Errorf("Got unexpected path: %s", path)
} }
@ -257,13 +275,14 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
}, },
Spec: v1.PersistentVolumeSpec{ Spec: v1.PersistentVolumeSpec{
PersistentVolumeSource: v1.PersistentVolumeSource{ PersistentVolumeSource: v1.PersistentVolumeSource{
HostPath: &v1.HostPathVolumeSource{Path: "foo"}, HostPath: &v1.HostPathVolumeSource{Path: "foo", Type: newHostPathType(string(v1.HostPathDirectoryOrCreate))},
}, },
ClaimRef: &v1.ObjectReference{ ClaimRef: &v1.ObjectReference{
Name: "claimA", Name: "claimA",
}, },
}, },
} }
defer os.RemoveAll("foo")
claim := &v1.PersistentVolumeClaim{ claim := &v1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
@ -296,3 +315,297 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
t.Errorf("Expected true for mounter.IsReadOnly") t.Errorf("Expected true for mounter.IsReadOnly")
} }
} }
type fakeFileTypeChecker struct {
desiredType string
}
func (fftc *fakeFileTypeChecker) getFileType(_ os.FileInfo) (v1.HostPathType, error) {
return *newHostPathType(fftc.desiredType), nil
}
func setUp() error {
err := os.MkdirAll("/tmp/ExistingFolder", os.FileMode(0755))
if err != nil {
return err
}
f, err := os.OpenFile("/tmp/ExistingFolder/foo", os.O_CREATE, os.FileMode(0644))
defer f.Close()
if err != nil {
return err
}
return nil
}
func tearDown() {
os.RemoveAll("/tmp/ExistingFolder")
}
func TestOSFileTypeChecker(t *testing.T) {
err := setUp()
if err != nil {
t.Error(err)
}
defer tearDown()
testCases := []struct {
name string
path string
desiredType string
isDir bool
isFile bool
isSocket bool
isBlock bool
isChar bool
}{
{
name: "Existing Folder",
path: "/tmp/ExistingFolder",
isDir: true,
},
{
name: "Existing File",
path: "/tmp/ExistingFolder/foo",
isFile: true,
},
{
name: "Existing Socket File",
path: "/tmp/ExistingFolder/foo",
desiredType: string(v1.HostPathSocket),
isSocket: true,
},
{
name: "Existing Character Device",
path: "/tmp/ExistingFolder/foo",
desiredType: string(v1.HostPathCharDev),
isChar: true,
},
{
name: "Existing Block Device",
path: "/tmp/ExistingFolder/foo",
desiredType: string(v1.HostPathBlockDev),
isBlock: true,
},
}
for i, tc := range testCases {
oftc, err := newOSFileTypeChecker(tc.path,
&fakeFileTypeChecker{desiredType: tc.desiredType})
if err != nil {
t.Errorf("[%d: %q] expect nil, but got %v", i, tc.name, err)
}
path := oftc.GetPath()
if path != tc.path {
t.Errorf("[%d: %q] got unexpected path: %s", i, tc.name, path)
}
exist := oftc.Exists()
if !exist {
t.Errorf("[%d: %q] path: %s does not exist", i, tc.name, path)
}
if tc.isDir {
if !oftc.IsDir() {
t.Errorf("[%d: %q] expected folder, got unexpected: %s", i, tc.name, path)
}
if oftc.IsFile() {
t.Errorf("[%d: %q] expected folder, got unexpected file: %s", i, tc.name, path)
}
if oftc.IsSocket() {
t.Errorf("[%d: %q] expected folder, got unexpected socket file: %s", i, tc.name, path)
}
if oftc.IsBlock() {
t.Errorf("[%d: %q] expected folder, got unexpected block device: %s", i, tc.name, path)
}
if oftc.IsChar() {
t.Errorf("[%d: %q] expected folder, got unexpected character device: %s", i, tc.name, path)
}
}
if tc.isFile {
if !oftc.IsFile() {
t.Errorf("[%d: %q] expected file, got unexpected: %s", i, tc.name, path)
}
if oftc.IsDir() {
t.Errorf("[%d: %q] expected file, got unexpected folder: %s", i, tc.name, path)
}
if oftc.IsSocket() {
t.Errorf("[%d: %q] expected file, got unexpected socket file: %s", i, tc.name, path)
}
if oftc.IsBlock() {
t.Errorf("[%d: %q] expected file, got unexpected block device: %s", i, tc.name, path)
}
if oftc.IsChar() {
t.Errorf("[%d: %q] expected file, got unexpected character device: %s", i, tc.name, path)
}
}
if tc.isSocket {
if !oftc.IsSocket() {
t.Errorf("[%d: %q] expected socket file, got unexpected: %s", i, tc.name, path)
}
if oftc.IsDir() {
t.Errorf("[%d: %q] expected socket file, got unexpected folder: %s", i, tc.name, path)
}
if !oftc.IsFile() {
t.Errorf("[%d: %q] expected socket file, got unexpected file: %s", i, tc.name, path)
}
if oftc.IsBlock() {
t.Errorf("[%d: %q] expected socket file, got unexpected block device: %s", i, tc.name, path)
}
if oftc.IsChar() {
t.Errorf("[%d: %q] expected socket file, got unexpected character device: %s", i, tc.name, path)
}
}
if tc.isChar {
if !oftc.IsChar() {
t.Errorf("[%d: %q] expected character device, got unexpected: %s", i, tc.name, path)
}
if oftc.IsDir() {
t.Errorf("[%d: %q] expected character device, got unexpected folder: %s", i, tc.name, path)
}
if !oftc.IsFile() {
t.Errorf("[%d: %q] expected character device, got unexpected file: %s", i, tc.name, path)
}
if oftc.IsSocket() {
t.Errorf("[%d: %q] expected character device, got unexpected socket file: %s", i, tc.name, path)
}
if oftc.IsBlock() {
t.Errorf("[%d: %q] expected character device, got unexpected block device: %s", i, tc.name, path)
}
}
if tc.isBlock {
if !oftc.IsBlock() {
t.Errorf("[%d: %q] expected block device, got unexpected: %s", i, tc.name, path)
}
if oftc.IsDir() {
t.Errorf("[%d: %q] expected block device, got unexpected folder: %s", i, tc.name, path)
}
if !oftc.IsFile() {
t.Errorf("[%d: %q] expected block device, got unexpected file: %s", i, tc.name, path)
}
if oftc.IsSocket() {
t.Errorf("[%d: %q] expected block device, got unexpected socket file: %s", i, tc.name, path)
}
if oftc.IsChar() {
t.Errorf("[%d: %q] expected block device, got unexpected character device: %s", i, tc.name, path)
}
}
}
}
type fakeHostPathTypeChecker struct {
name string
path string
exists bool
isDir bool
isFile bool
isSocket bool
isBlock bool
isChar bool
validpathType []*v1.HostPathType
invalidpathType []*v1.HostPathType
}
func (ftc *fakeHostPathTypeChecker) MakeFile() error { return nil }
func (ftc *fakeHostPathTypeChecker) MakeDir() error { return nil }
func (ftc *fakeHostPathTypeChecker) Exists() bool { return ftc.exists }
func (ftc *fakeHostPathTypeChecker) IsFile() bool { return ftc.isFile }
func (ftc *fakeHostPathTypeChecker) IsDir() bool { return ftc.isDir }
func (ftc *fakeHostPathTypeChecker) IsBlock() bool { return ftc.isBlock }
func (ftc *fakeHostPathTypeChecker) IsChar() bool { return ftc.isChar }
func (ftc *fakeHostPathTypeChecker) IsSocket() bool { return ftc.isSocket }
func (ftc *fakeHostPathTypeChecker) GetPath() string { return ftc.path }
func TestHostPathTypeCheckerInternal(t *testing.T) {
testCases := []fakeHostPathTypeChecker{
{
name: "Existing Folder",
path: "/existingFolder",
isDir: true,
exists: true,
validpathType: newHostPathTypeList(string(v1.HostPathDirectoryOrCreate), string(v1.HostPathDirectory)),
invalidpathType: newHostPathTypeList(string(v1.HostPathFileOrCreate), string(v1.HostPathFile),
string(v1.HostPathSocket), string(v1.HostPathCharDev), string(v1.HostPathBlockDev)),
},
{
name: "New Folder",
path: "/newFolder",
isDir: false,
exists: false,
validpathType: newHostPathTypeList(string(v1.HostPathDirectoryOrCreate)),
invalidpathType: newHostPathTypeList(string(v1.HostPathDirectory), string(v1.HostPathFile),
string(v1.HostPathSocket), string(v1.HostPathCharDev), string(v1.HostPathBlockDev)),
},
{
name: "Existing File",
path: "/existingFile",
isFile: true,
exists: true,
validpathType: newHostPathTypeList(string(v1.HostPathFileOrCreate), string(v1.HostPathFile)),
invalidpathType: newHostPathTypeList(string(v1.HostPathDirectoryOrCreate), string(v1.HostPathDirectory),
string(v1.HostPathSocket), string(v1.HostPathCharDev), string(v1.HostPathBlockDev)),
},
{
name: "New File",
path: "/newFile",
isFile: false,
exists: false,
validpathType: newHostPathTypeList(string(v1.HostPathFileOrCreate)),
invalidpathType: newHostPathTypeList(string(v1.HostPathDirectory),
string(v1.HostPathSocket), string(v1.HostPathCharDev), string(v1.HostPathBlockDev)),
},
{
name: "Existing Socket",
path: "/existing.socket",
isSocket: true,
isFile: true,
exists: true,
validpathType: newHostPathTypeList(string(v1.HostPathSocket), string(v1.HostPathFileOrCreate), string(v1.HostPathFile)),
invalidpathType: newHostPathTypeList(string(v1.HostPathDirectoryOrCreate), string(v1.HostPathDirectory),
string(v1.HostPathCharDev), string(v1.HostPathBlockDev)),
},
{
name: "Existing Character Device",
path: "/existing.char",
isChar: true,
isFile: true,
exists: true,
validpathType: newHostPathTypeList(string(v1.HostPathCharDev), string(v1.HostPathFileOrCreate), string(v1.HostPathFile)),
invalidpathType: newHostPathTypeList(string(v1.HostPathDirectoryOrCreate), string(v1.HostPathDirectory),
string(v1.HostPathSocket), string(v1.HostPathBlockDev)),
},
{
name: "Existing Block Device",
path: "/existing.block",
isBlock: true,
isFile: true,
exists: true,
validpathType: newHostPathTypeList(string(v1.HostPathBlockDev), string(v1.HostPathFileOrCreate), string(v1.HostPathFile)),
invalidpathType: newHostPathTypeList(string(v1.HostPathDirectoryOrCreate), string(v1.HostPathDirectory),
string(v1.HostPathSocket), string(v1.HostPathCharDev)),
},
}
for i, tc := range testCases {
for _, pathType := range tc.validpathType {
err := checkTypeInternal(&tc, pathType)
if err != nil {
t.Errorf("[%d: %q] [%q] expected nil, got %v", i, tc.name, string(*pathType), err)
}
}
for _, pathType := range tc.invalidpathType {
checkResult := checkTypeInternal(&tc, pathType)
if checkResult == nil {
t.Errorf("[%d: %q] [%q] expected error, got nil", i, tc.name, string(*pathType))
}
}
}
}

View File

@ -0,0 +1,40 @@
// +build linux darwin
/*
Copyright 2017 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 host_path
import (
"fmt"
"os"
"syscall"
"k8s.io/api/core/v1"
)
func (dftc *defaultFileTypeChecker) getFileType(info os.FileInfo) (v1.HostPathType, error) {
mode := info.Sys().(*syscall.Stat_t).Mode
switch mode & syscall.S_IFMT {
case syscall.S_IFSOCK:
return v1.HostPathSocket, nil
case syscall.S_IFBLK:
return v1.HostPathBlockDev, nil
case syscall.S_IFCHR:
return v1.HostPathCharDev, nil
}
return "", fmt.Errorf("only recognise socket, block device and character device")
}

View File

@ -0,0 +1,38 @@
/*
Copyright 2017 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 host_path
import (
"fmt"
"os"
"syscall"
"k8s.io/api/core/v1"
)
func (dftc *defaultFileTypeChecker) getFileType(info os.FileInfo) (v1.HostPathType, error) {
mode := info.Sys().(*syscall.Win32FileAttributeData).FileAttributes
switch mode & syscall.S_IFMT {
case syscall.S_IFSOCK:
return v1.HostPathSocket, nil
case syscall.S_IFBLK:
return v1.HostPathBlockDev, nil
case syscall.S_IFCHR:
return v1.HostPathCharDev, nil
}
return "", fmt.Errorf("only recognise socket, block device and character device")
}

View File

@ -0,0 +1,150 @@
// +build linux
/*
Copyright 2017 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 host_path
import (
"fmt"
"k8s.io/utils/exec"
)
const (
hostProcMountsNamespace = "/rootfs/proc/1/ns/mnt"
nsenterCmd = "nsenter"
statCmd = "stat"
touchCmd = "touch"
mkdirCmd = "mkdir"
)
// nsenterFileTypeChecker is part of experimental support for running the kubelet
// in a container. nsenterFileTypeChecker works by executing "nsenter" to run commands in
// the host's mount namespace.
//
// nsenterFileTypeChecker requires:
//
// 1. The host's root filesystem must be available at "/rootfs";
// 2. The "nsenter" binary must be on the Kubelet process' PATH in the container's
// filesystem;
// 3. The Kubelet process must have CAP_SYS_ADMIN (required by "nsenter"); at
// the present, this effectively means that the kubelet is running in a
// privileged container;
// 4. The host image must have "stat", "touch", "mkdir" binaries in "/bin", "/usr/sbin", or "/usr/bin";
type nsenterFileTypeChecker struct {
path string
exists bool
}
func newNsenterFileTypeChecker(path string) (hostPathTypeChecker, error) {
ftc := &nsenterFileTypeChecker{path: path}
ftc.Exists()
return ftc, nil
}
func (ftc *nsenterFileTypeChecker) Exists() bool {
args := []string{
fmt.Sprintf("--mount=%s", hostProcMountsNamespace),
"--",
"ls",
ftc.path,
}
exec := exec.New()
_, err := exec.Command(nsenterCmd, args...).CombinedOutput()
if err == nil {
ftc.exists = true
}
return ftc.exists
}
func (ftc *nsenterFileTypeChecker) IsFile() bool {
if !ftc.Exists() {
return false
}
return !ftc.IsDir()
}
func (ftc *nsenterFileTypeChecker) MakeFile() error {
args := []string{
fmt.Sprintf("--mount=%s", hostProcMountsNamespace),
"--",
touchCmd,
ftc.path,
}
exec := exec.New()
if _, err := exec.Command(nsenterCmd, args...).CombinedOutput(); err != nil {
return err
}
return nil
}
func (ftc *nsenterFileTypeChecker) IsDir() bool {
return ftc.checkMimetype("directory")
}
func (ftc *nsenterFileTypeChecker) MakeDir() error {
args := []string{
fmt.Sprintf("--mount=%s", hostProcMountsNamespace),
"--",
mkdirCmd,
"-p",
ftc.path,
}
exec := exec.New()
if _, err := exec.Command(nsenterCmd, args...).CombinedOutput(); err != nil {
return err
}
return nil
}
func (ftc *nsenterFileTypeChecker) IsBlock() bool {
return ftc.checkMimetype("block special file")
}
func (ftc *nsenterFileTypeChecker) IsChar() bool {
return ftc.checkMimetype("character special file")
}
func (ftc *nsenterFileTypeChecker) IsSocket() bool {
return ftc.checkMimetype("socket")
}
func (ftc *nsenterFileTypeChecker) GetPath() string {
return ftc.path
}
func (ftc *nsenterFileTypeChecker) checkMimetype(checkedType string) bool {
if !ftc.Exists() {
return false
}
args := []string{
fmt.Sprintf("--mount=%s", hostProcMountsNamespace),
"--",
statCmd,
"-L",
`--printf "%F"`,
ftc.path,
}
exec := exec.New()
outputBytes, err := exec.Command(nsenterCmd, args...).CombinedOutput()
if err != nil {
return false
}
return string(outputBytes) == checkedType
}

View File

@ -0,0 +1,66 @@
// +build !linux
/*
Copyright 2017 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 host_path
type nsenterFileTypeChecker struct {
path string
exists bool
}
func newNsenterFileTypeChecker(path string) (hostPathTypeChecker, error) {
ftc := &nsenterFileTypeChecker{path: path}
ftc.Exists()
return ftc, nil
}
func (ftc *nsenterFileTypeChecker) Exists() bool {
return false
}
func (ftc *nsenterFileTypeChecker) IsFile() bool {
return false
}
func (ftc *nsenterFileTypeChecker) MakeFile() error {
return nil
}
func (ftc *nsenterFileTypeChecker) IsDir() bool {
return false
}
func (ftc *nsenterFileTypeChecker) MakeDir() error {
return nil
}
func (ftc *nsenterFileTypeChecker) IsBlock() bool {
return false
}
func (ftc *nsenterFileTypeChecker) IsChar() bool {
return false
}
func (ftc *nsenterFileTypeChecker) IsSocket() bool {
return false
}
func (ftc *nsenterFileTypeChecker) GetPath() string {
return ftc.path
}

View File

@ -66,6 +66,8 @@ type VolumeOptions struct {
CloudTags *map[string]string CloudTags *map[string]string
// Volume provisioning parameters from StorageClass // Volume provisioning parameters from StorageClass
Parameters map[string]string Parameters map[string]string
// This flag helps identify whether kubelet is running in a container
Containerized bool
} }
// VolumePlugin is an interface to volume plugins that can be used on a // VolumePlugin is an interface to volume plugins that can be used on a

File diff suppressed because it is too large Load Diff

View File

@ -1223,8 +1223,15 @@ message HostAlias {
// Host path volumes do not support ownership management or SELinux relabeling. // Host path volumes do not support ownership management or SELinux relabeling.
message HostPathVolumeSource { message HostPathVolumeSource {
// Path of the directory on the host. // Path of the directory on the host.
// If the path is a symlink, it will follow the link to the real path.
// More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath // More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath
optional string path = 1; optional string path = 1;
// Type for HostPath Volume
// Defaults to ""
// More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath
// +optional
optional string type = 2;
} }
// Represents an ISCSI disk. // Represents an ISCSI disk.

View File

@ -11294,6 +11294,32 @@ func (x *PersistentVolumeClaimPhase) CodecDecodeSelf(d *codec1978.Decoder) {
} }
} }
func (x HostPathType) CodecEncodeSelf(e *codec1978.Encoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperEncoder(e)
_, _, _ = h, z, r
yym1 := z.EncBinary()
_ = yym1
if false {
} else if z.HasExtensions() && z.EncExt(x) {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x))
}
}
func (x *HostPathType) CodecDecodeSelf(d *codec1978.Decoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
yym1 := z.DecBinary()
_ = yym1
if false {
} else if z.HasExtensions() && z.DecExt(x) {
} else {
*((*string)(x)) = r.DecodeString()
}
}
func (x *HostPathVolumeSource) CodecEncodeSelf(e *codec1978.Encoder) { func (x *HostPathVolumeSource) CodecEncodeSelf(e *codec1978.Encoder) {
var h codecSelfer1234 var h codecSelfer1234
z, r := codec1978.GenHelperEncoder(e) z, r := codec1978.GenHelperEncoder(e)
@ -11308,12 +11334,13 @@ func (x *HostPathVolumeSource) CodecEncodeSelf(e *codec1978.Encoder) {
} else { } else {
yysep2 := !z.EncBinary() yysep2 := !z.EncBinary()
yy2arr2 := z.EncBasicHandle().StructToArray yy2arr2 := z.EncBasicHandle().StructToArray
var yyq2 [1]bool var yyq2 [2]bool
_, _, _ = yysep2, yyq2, yy2arr2 _, _, _ = yysep2, yyq2, yy2arr2
const yyr2 bool = false const yyr2 bool = false
yyq2[1] = x.Type != nil
var yynn2 int var yynn2 int
if yyr2 || yy2arr2 { if yyr2 || yy2arr2 {
r.EncodeArrayStart(1) r.EncodeArrayStart(2)
} else { } else {
yynn2 = 1 yynn2 = 1
for _, b := range yyq2 { for _, b := range yyq2 {
@ -11343,6 +11370,31 @@ func (x *HostPathVolumeSource) CodecEncodeSelf(e *codec1978.Encoder) {
r.EncodeString(codecSelferC_UTF81234, string(x.Path)) r.EncodeString(codecSelferC_UTF81234, string(x.Path))
} }
} }
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if yyq2[1] {
if x.Type == nil {
r.EncodeNil()
} else {
yy7 := *x.Type
yy7.CodecEncodeSelf(e)
}
} else {
r.EncodeNil()
}
} else {
if yyq2[1] {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("type"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
if x.Type == nil {
r.EncodeNil()
} else {
yy9 := *x.Type
yy9.CodecEncodeSelf(e)
}
}
}
if yyr2 || yy2arr2 { if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayEnd1234) z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
} else { } else {
@ -11416,6 +11468,17 @@ func (x *HostPathVolumeSource) codecDecodeSelfFromMap(l int, d *codec1978.Decode
*((*string)(yyv4)) = r.DecodeString() *((*string)(yyv4)) = r.DecodeString()
} }
} }
case "type":
if r.TryDecodeAsNil() {
if x.Type != nil {
x.Type = nil
}
} else {
if x.Type == nil {
x.Type = new(HostPathType)
}
x.Type.CodecDecodeSelf(d)
}
default: default:
z.DecStructFieldNotFound(-1, yys3) z.DecStructFieldNotFound(-1, yys3)
} // end switch yys3 } // end switch yys3
@ -11427,16 +11490,16 @@ func (x *HostPathVolumeSource) codecDecodeSelfFromArray(l int, d *codec1978.Deco
var h codecSelfer1234 var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d) z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r _, _, _ = h, z, r
var yyj6 int var yyj7 int
var yyb6 bool var yyb7 bool
var yyhl6 bool = l >= 0 var yyhl7 bool = l >= 0
yyj6++ yyj7++
if yyhl6 { if yyhl7 {
yyb6 = yyj6 > l yyb7 = yyj7 > l
} else { } else {
yyb6 = r.CheckBreak() yyb7 = r.CheckBreak()
} }
if yyb6 { if yyb7 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return return
} }
@ -11444,26 +11507,47 @@ func (x *HostPathVolumeSource) codecDecodeSelfFromArray(l int, d *codec1978.Deco
if r.TryDecodeAsNil() { if r.TryDecodeAsNil() {
x.Path = "" x.Path = ""
} else { } else {
yyv7 := &x.Path yyv8 := &x.Path
yym8 := z.DecBinary() yym9 := z.DecBinary()
_ = yym8 _ = yym9
if false { if false {
} else { } else {
*((*string)(yyv7)) = r.DecodeString() *((*string)(yyv8)) = r.DecodeString()
} }
} }
for { yyj7++
yyj6++ if yyhl7 {
if yyhl6 { yyb7 = yyj7 > l
yyb6 = yyj6 > l } else {
} else { yyb7 = r.CheckBreak()
yyb6 = r.CheckBreak() }
if yyb7 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
if x.Type != nil {
x.Type = nil
} }
if yyb6 { } else {
if x.Type == nil {
x.Type = new(HostPathType)
}
x.Type.CodecDecodeSelf(d)
}
for {
yyj7++
if yyhl7 {
yyb7 = yyj7 > l
} else {
yyb7 = r.CheckBreak()
}
if yyb7 {
break break
} }
z.DecSendContainerState(codecSelfer_containerArrayElem1234) z.DecSendContainerState(codecSelfer_containerArrayElem1234)
z.DecStructFieldNotFound(yyj6-1, "") z.DecStructFieldNotFound(yyj7-1, "")
} }
z.DecSendContainerState(codecSelfer_containerArrayEnd1234) z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
} }

View File

@ -681,12 +681,41 @@ const (
ClaimLost PersistentVolumeClaimPhase = "Lost" ClaimLost PersistentVolumeClaimPhase = "Lost"
) )
type HostPathType string
const (
// For backwards compatible, leave it empty if unset
HostPathUnset HostPathType = ""
// If nothing exists at the given path, an empty directory will be created there
// as needed with file mode 0755, having the same group and ownership with Kubelet.
HostPathDirectoryOrCreate HostPathType = "DirectoryOrCreate"
// A directory must exist at the given path
HostPathDirectory HostPathType = "Directory"
// If nothing exists at the given path, an empty file will be created there
// as needed with file mode 0644, having the same group and ownership with Kubelet.
HostPathFileOrCreate HostPathType = "FileOrCreate"
// A file must exist at the given path
HostPathFile HostPathType = "File"
// A UNIX socket must exist at the given path
HostPathSocket HostPathType = "Socket"
// A character device must exist at the given path
HostPathCharDev HostPathType = "CharDevice"
// A block device must exist at the given path
HostPathBlockDev HostPathType = "BlockDevice"
)
// Represents a host path mapped into a pod. // Represents a host path mapped into a pod.
// Host path volumes do not support ownership management or SELinux relabeling. // Host path volumes do not support ownership management or SELinux relabeling.
type HostPathVolumeSource struct { type HostPathVolumeSource struct {
// Path of the directory on the host. // Path of the directory on the host.
// If the path is a symlink, it will follow the link to the real path.
// More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath // More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath
Path string `json:"path" protobuf:"bytes,1,opt,name=path"` Path string `json:"path" protobuf:"bytes,1,opt,name=path"`
// Type for HostPath Volume
// Defaults to ""
// More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath
// +optional
Type *HostPathType `json:"type,omitempty" protobuf:"bytes,2,opt,name=type"`
} }
// Represents an empty directory for a pod. // Represents an empty directory for a pod.

View File

@ -655,7 +655,8 @@ func (HostAlias) SwaggerDoc() map[string]string {
var map_HostPathVolumeSource = map[string]string{ var map_HostPathVolumeSource = map[string]string{
"": "Represents a host path mapped into a pod. Host path volumes do not support ownership management or SELinux relabeling.", "": "Represents a host path mapped into a pod. Host path volumes do not support ownership management or SELinux relabeling.",
"path": "Path of the directory on the host. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath", "path": "Path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath",
"type": "Type for HostPath Volume Defaults to \"\" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath",
} }
func (HostPathVolumeSource) SwaggerDoc() map[string]string { func (HostPathVolumeSource) SwaggerDoc() map[string]string {

View File

@ -2303,6 +2303,15 @@ func (in *HostAlias) DeepCopy() *HostAlias {
// 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 *HostPathVolumeSource) DeepCopyInto(out *HostPathVolumeSource) { func (in *HostPathVolumeSource) DeepCopyInto(out *HostPathVolumeSource) {
*out = *in *out = *in
if in.Type != nil {
in, out := &in.Type, &out.Type
if *in == nil {
*out = nil
} else {
*out = new(HostPathType)
**out = **in
}
}
return return
} }
@ -3558,7 +3567,7 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) {
*out = nil *out = nil
} else { } else {
*out = new(HostPathVolumeSource) *out = new(HostPathVolumeSource)
**out = **in (*in).DeepCopyInto(*out)
} }
} }
if in.Glusterfs != nil { if in.Glusterfs != nil {
@ -5825,7 +5834,7 @@ func (in *VolumeSource) DeepCopyInto(out *VolumeSource) {
*out = nil *out = nil
} else { } else {
*out = new(HostPathVolumeSource) *out = new(HostPathVolumeSource)
**out = **in (*in).DeepCopyInto(*out)
} }
} }
if in.EmptyDir != nil { if in.EmptyDir != nil {

View File

@ -130,6 +130,8 @@ func (config *KubeletManagedHostConfig) getEtcHostsContent(podName, containerNam
} }
func (config *KubeletManagedHostConfig) createPodSpec(podName string) *v1.Pod { func (config *KubeletManagedHostConfig) createPodSpec(podName string) *v1.Pod {
hostPathType := new(v1.HostPathType)
*hostPathType = v1.HostPathType(string(v1.HostPathFileOrCreate))
pod := &v1.Pod{ pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: podName, Name: podName,
@ -176,6 +178,7 @@ func (config *KubeletManagedHostConfig) createPodSpec(podName string) *v1.Pod {
VolumeSource: v1.VolumeSource{ VolumeSource: v1.VolumeSource{
HostPath: &v1.HostPathVolumeSource{ HostPath: &v1.HostPathVolumeSource{
Path: "/etc/hosts", Path: "/etc/hosts",
Type: hostPathType,
}, },
}, },
}, },

View File

@ -74,6 +74,9 @@ var _ = framework.KubeDescribe("ContainerLogPath", func() {
expectedlogFile := logDir + "/" + logPodName + "_" + ns + "_" + logContName + "-" + logConID.ID + ".log" expectedlogFile := logDir + "/" + logPodName + "_" + ns + "_" + logContName + "-" + logConID.ID + ".log"
hostPathType := new(v1.HostPathType)
*hostPathType = v1.HostPathType(string(v1.HostPathFileOrCreate))
checkPod := &v1.Pod{ checkPod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: checkPodName, Name: checkPodName,
@ -104,6 +107,7 @@ var _ = framework.KubeDescribe("ContainerLogPath", func() {
VolumeSource: v1.VolumeSource{ VolumeSource: v1.VolumeSource{
HostPath: &v1.HostPathVolumeSource{ HostPath: &v1.HostPathVolumeSource{
Path: expectedlogFile, Path: expectedlogFile,
Type: hostPathType,
}, },
}, },
}, },

View File

@ -161,6 +161,8 @@ var _ = framework.KubeDescribe("NodeProblemDetector", func() {
}) })
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
By("Create the node problem detector") By("Create the node problem detector")
hostPathType := new(v1.HostPathType)
*hostPathType = v1.HostPathType(string(v1.HostPathFileOrCreate))
f.PodClient().CreateSync(&v1.Pod{ f.PodClient().CreateSync(&v1.Pod{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
@ -186,7 +188,10 @@ var _ = framework.KubeDescribe("NodeProblemDetector", func() {
{ {
Name: localtimeVolume, Name: localtimeVolume,
VolumeSource: v1.VolumeSource{ VolumeSource: v1.VolumeSource{
HostPath: &v1.HostPathVolumeSource{Path: etcLocaltime}, HostPath: &v1.HostPathVolumeSource{
Path: etcLocaltime,
Type: hostPathType,
},
}, },
}, },
}, },

View File

@ -63,6 +63,7 @@ spec:
name: srvkube name: srvkube
- hostPath: - hostPath:
path: /var/log/kube-apiserver.log path: /var/log/kube-apiserver.log
type: FileOrCreate
name: logfile name: logfile
- hostPath: - hostPath:
path: /etc/ssl path: /etc/ssl

View File

@ -55,6 +55,7 @@ spec:
name: srvkube name: srvkube
- hostPath: - hostPath:
path: /var/log/kube-controller-manager.log path: /var/log/kube-controller-manager.log
type: FileOrCreate
name: logfile name: logfile
- hostPath: - hostPath:
path: /etc/ssl path: /etc/ssl

View File

@ -27,4 +27,5 @@ spec:
volumes: volumes:
- hostPath: - hostPath:
path: /var/log/kube-scheduler.log path: /var/log/kube-scheduler.log
type: FileOrCreate
name: logfile name: logfile

View File

@ -48,3 +48,4 @@ spec:
- name: varlogetcd - name: varlogetcd
hostPath: hostPath:
path: /var/log/etcd-events.log path: /var/log/etcd-events.log
type: FileOrCreate

View File

@ -47,3 +47,4 @@ spec:
- name: varlogetcd - name: varlogetcd
hostPath: hostPath:
path: /var/log/etcd.log path: /var/log/etcd.log
type: FileOrCreate

View File

@ -31,3 +31,4 @@ spec:
- name: varlog - name: varlog
hostPath: hostPath:
path: /var/log/kube-addon-manager.log path: /var/log/kube-addon-manager.log
type: FileOrCreate

View File

@ -56,6 +56,7 @@ spec:
- name: logfile - name: logfile
hostPath: hostPath:
path: /var/log/kube-apiserver.log path: /var/log/kube-apiserver.log
type: FileOrCreate
- name: etcssl - name: etcssl
hostPath: hostPath:
path: /etc/ssl path: /etc/ssl

View File

@ -45,6 +45,7 @@ spec:
- name: logfile - name: logfile
hostPath: hostPath:
path: /var/log/kube-controller-manager.log path: /var/log/kube-controller-manager.log
type: FileOrCreate
- name: etcssl - name: etcssl
hostPath: hostPath:
path: /etc/ssl path: /etc/ssl

View File

@ -40,3 +40,4 @@ spec:
- name: logfile - name: logfile
hostPath: hostPath:
path: /var/log/kube-scheduler.log path: /var/log/kube-scheduler.log
type: FileOrCreate