mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-05 10:19:50 +00:00
support Azure File Service volume
Signed-off-by: Huamin Chen <hchen@redhat.com>
This commit is contained in:
parent
242000d790
commit
d7e4b826b9
@ -14914,6 +14914,10 @@
|
|||||||
"$ref": "v1.FlexVolumeSource",
|
"$ref": "v1.FlexVolumeSource",
|
||||||
"description": "FlexVolume represents a generic volume resource that is provisioned/attached using a exec based plugin. This is an alpha feature and may change in future."
|
"description": "FlexVolume represents a generic volume resource that is provisioned/attached using a exec based plugin. This is an alpha feature and may change in future."
|
||||||
},
|
},
|
||||||
|
"azureFile": {
|
||||||
|
"$ref": "v1.AzureFileVolumeSource",
|
||||||
|
"description": "AzureFile represents an Azure File Service mount on the host and bind mount to the pod."
|
||||||
|
},
|
||||||
"accessModes": {
|
"accessModes": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
@ -15268,6 +15272,28 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"v1.AzureFileVolumeSource": {
|
||||||
|
"id": "v1.AzureFileVolumeSource",
|
||||||
|
"description": "AzureFile represents an Azure File Service mount on the host and bind mount to the pod.",
|
||||||
|
"required": [
|
||||||
|
"secretName",
|
||||||
|
"shareName"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"secretName": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "the name of secret that contains Azure Storage Account Name and Key"
|
||||||
|
},
|
||||||
|
"shareName": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Share Name"
|
||||||
|
},
|
||||||
|
"readOnly": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"v1.PersistentVolumeStatus": {
|
"v1.PersistentVolumeStatus": {
|
||||||
"id": "v1.PersistentVolumeStatus",
|
"id": "v1.PersistentVolumeStatus",
|
||||||
"description": "PersistentVolumeStatus is the current status of a persistent volume.",
|
"description": "PersistentVolumeStatus is the current status of a persistent volume.",
|
||||||
@ -15498,6 +15524,10 @@
|
|||||||
"fc": {
|
"fc": {
|
||||||
"$ref": "v1.FCVolumeSource",
|
"$ref": "v1.FCVolumeSource",
|
||||||
"description": "FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod."
|
"description": "FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod."
|
||||||
|
},
|
||||||
|
"azureFile": {
|
||||||
|
"$ref": "v1.AzureFileVolumeSource",
|
||||||
|
"description": "AzureFile represents an Azure File Service mount on the host and bind mount to the pod."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -4333,6 +4333,10 @@
|
|||||||
"fc": {
|
"fc": {
|
||||||
"$ref": "v1.FCVolumeSource",
|
"$ref": "v1.FCVolumeSource",
|
||||||
"description": "FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod."
|
"description": "FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod."
|
||||||
|
},
|
||||||
|
"azureFile": {
|
||||||
|
"$ref": "v1.AzureFileVolumeSource",
|
||||||
|
"description": "AzureFile represents an Azure File Service mount on the host and bind mount to the pod."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -4779,6 +4783,28 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"v1.AzureFileVolumeSource": {
|
||||||
|
"id": "v1.AzureFileVolumeSource",
|
||||||
|
"description": "AzureFile represents an Azure File Service mount on the host and bind mount to the pod.",
|
||||||
|
"required": [
|
||||||
|
"secretName",
|
||||||
|
"shareName"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"secretName": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "the name of secret that contains Azure Storage Account Name and Key"
|
||||||
|
},
|
||||||
|
"shareName": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Share Name"
|
||||||
|
},
|
||||||
|
"readOnly": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"v1.Container": {
|
"v1.Container": {
|
||||||
"id": "v1.Container",
|
"id": "v1.Container",
|
||||||
"description": "A single application container that you want to run within a pod.",
|
"description": "A single application container that you want to run within a pod.",
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
// Volume plugins
|
// Volume plugins
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
"k8s.io/kubernetes/pkg/volume/aws_ebs"
|
"k8s.io/kubernetes/pkg/volume/aws_ebs"
|
||||||
|
"k8s.io/kubernetes/pkg/volume/azure_file"
|
||||||
"k8s.io/kubernetes/pkg/volume/cephfs"
|
"k8s.io/kubernetes/pkg/volume/cephfs"
|
||||||
"k8s.io/kubernetes/pkg/volume/cinder"
|
"k8s.io/kubernetes/pkg/volume/cinder"
|
||||||
"k8s.io/kubernetes/pkg/volume/downwardapi"
|
"k8s.io/kubernetes/pkg/volume/downwardapi"
|
||||||
@ -78,7 +79,7 @@ func ProbeVolumePlugins(pluginDir string) []volume.VolumePlugin {
|
|||||||
allPlugins = append(allPlugins, fc.ProbeVolumePlugins()...)
|
allPlugins = append(allPlugins, fc.ProbeVolumePlugins()...)
|
||||||
allPlugins = append(allPlugins, flocker.ProbeVolumePlugins()...)
|
allPlugins = append(allPlugins, flocker.ProbeVolumePlugins()...)
|
||||||
allPlugins = append(allPlugins, flexvolume.ProbeVolumePlugins(pluginDir)...)
|
allPlugins = append(allPlugins, flexvolume.ProbeVolumePlugins(pluginDir)...)
|
||||||
|
allPlugins = append(allPlugins, azure_file.ProbeVolumePlugins()...)
|
||||||
return allPlugins
|
return allPlugins
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2364,6 +2364,54 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="sect2">
|
||||||
|
<h3 id="_v1_azurefilevolumesource">v1.AzureFileVolumeSource</h3>
|
||||||
|
<div class="paragraph">
|
||||||
|
<p>AzureFile represents an Azure File Service mount on the host and bind mount to the pod.</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">secretName</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">the name of secret that contains Azure Storage Account Name and Key</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">shareName</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Share Name</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">readOnly</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="sect2">
|
<div class="sect2">
|
||||||
<h3 id="_v1_hostpathvolumesource">v1.HostPathVolumeSource</h3>
|
<h3 id="_v1_hostpathvolumesource">v1.HostPathVolumeSource</h3>
|
||||||
@ -3668,6 +3716,13 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
|
|||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_fcvolumesource">v1.FCVolumeSource</a></p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_fcvolumesource">v1.FCVolumeSource</a></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">azureFile</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">AzureFile represents an Azure File Service mount on the host and bind mount to the pod.</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_azurefilevolumesource">v1.AzureFileVolumeSource</a></p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@ -4772,7 +4827,7 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
|
|||||||
</div>
|
</div>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<div id="footer-text">
|
<div id="footer-text">
|
||||||
Last updated 2016-02-08 13:55:53 UTC
|
Last updated 2016-02-09 01:06:27 UTC
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -1891,6 +1891,54 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="sect2">
|
||||||
|
<h3 id="_v1_azurefilevolumesource">v1.AzureFileVolumeSource</h3>
|
||||||
|
<div class="paragraph">
|
||||||
|
<p>AzureFile represents an Azure File Service mount on the host and bind mount to the pod.</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">secretName</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">the name of secret that contains Azure Storage Account Name and Key</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">shareName</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Share Name</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">readOnly</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="sect2">
|
<div class="sect2">
|
||||||
<h3 id="_v1_iscsivolumesource">v1.ISCSIVolumeSource</h3>
|
<h3 id="_v1_iscsivolumesource">v1.ISCSIVolumeSource</h3>
|
||||||
@ -3235,6 +3283,13 @@ The resulting set of endpoints can be viewed as:<br>
|
|||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_fcvolumesource">v1.FCVolumeSource</a></p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_fcvolumesource">v1.FCVolumeSource</a></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">azureFile</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">AzureFile represents an Azure File Service mount on the host and bind mount to the pod.</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_azurefilevolumesource">v1.AzureFileVolumeSource</a></p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@ -5180,6 +5235,13 @@ The resulting set of endpoints can be viewed as:<br>
|
|||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">azureFile</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">AzureFile represents an Azure File Service mount on the host and bind mount to the pod.</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_azurefilevolumesource">v1.AzureFileVolumeSource</a></p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">accessModes</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">accessModes</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">AccessModes contains all ways the volume can be mounted. More info: <a href="http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#access-modes">http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#access-modes</a></p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">AccessModes contains all ways the volume can be mounted. More info: <a href="http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#access-modes">http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#access-modes</a></p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
@ -7316,7 +7378,7 @@ The resulting set of endpoints can be viewed as:<br>
|
|||||||
</div>
|
</div>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<div id="footer-text">
|
<div id="footer-text">
|
||||||
Last updated 2016-02-02 15:03:04 UTC
|
Last updated 2016-02-08 13:47:29 UTC
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -67,6 +67,7 @@ Familiarity with [pods](pods.md) is suggested.
|
|||||||
- [persistentVolumeClaim](#persistentvolumeclaim)
|
- [persistentVolumeClaim](#persistentvolumeclaim)
|
||||||
- [downwardAPI](#downwardapi)
|
- [downwardAPI](#downwardapi)
|
||||||
- [FlexVolume](#flexvolume)
|
- [FlexVolume](#flexvolume)
|
||||||
|
- [AzureFileVolume](#azurefilevolume)
|
||||||
- [Resources](#resources)
|
- [Resources](#resources)
|
||||||
|
|
||||||
<!-- END MUNGE: GENERATED_TOC -->
|
<!-- END MUNGE: GENERATED_TOC -->
|
||||||
@ -124,6 +125,7 @@ Kubernetes supports several types of Volumes:
|
|||||||
* `secret`
|
* `secret`
|
||||||
* `persistentVolumeClaim`
|
* `persistentVolumeClaim`
|
||||||
* `downwardAPI`
|
* `downwardAPI`
|
||||||
|
* `azureFileVolume`
|
||||||
|
|
||||||
We welcome additional contributions.
|
We welcome additional contributions.
|
||||||
|
|
||||||
@ -427,6 +429,13 @@ an alpha feature and may change in future.
|
|||||||
|
|
||||||
More details are in [here](../../examples/flexvolume/README.md)
|
More details are in [here](../../examples/flexvolume/README.md)
|
||||||
|
|
||||||
|
### AzureFileVolume
|
||||||
|
|
||||||
|
A `AzureFileVolume` is used to mount a Microsoft Azure File Volume (SMB 2.1 and 3.0)
|
||||||
|
into a Pod.
|
||||||
|
|
||||||
|
More details can be found [here](../../examples/azure_file/README.md)
|
||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
|
|
||||||
The storage media (Disk, SSD, etc) of an `emptyDir` volume is determined by the
|
The storage media (Disk, SSD, etc) of an `emptyDir` volume is determined by the
|
||||||
@ -440,7 +449,6 @@ request a certain amount of space using a [resource](compute-resources.md)
|
|||||||
specification, and to select the type of media to use, for clusters that have
|
specification, and to select the type of media to use, for clusters that have
|
||||||
several media types.
|
several media types.
|
||||||
|
|
||||||
|
|
||||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
[]()
|
[]()
|
||||||
<!-- END MUNGE: GENERATED_ANALYTICS -->
|
<!-- END MUNGE: GENERATED_ANALYTICS -->
|
||||||
|
64
examples/azure_file/README.md
Normal file
64
examples/azure_file/README.md
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<!-- BEGIN MUNGE: UNVERSIONED_WARNING -->
|
||||||
|
|
||||||
|
<!-- BEGIN STRIP_FOR_RELEASE -->
|
||||||
|
|
||||||
|
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
|
||||||
|
width="25" height="25">
|
||||||
|
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
|
||||||
|
width="25" height="25">
|
||||||
|
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
|
||||||
|
width="25" height="25">
|
||||||
|
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
|
||||||
|
width="25" height="25">
|
||||||
|
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
|
||||||
|
width="25" height="25">
|
||||||
|
|
||||||
|
<h2>PLEASE NOTE: This document applies to the HEAD of the source tree</h2>
|
||||||
|
|
||||||
|
If you are using a released version of Kubernetes, you should
|
||||||
|
refer to the docs that go with that version.
|
||||||
|
|
||||||
|
Documentation for other releases can be found at
|
||||||
|
[releases.k8s.io](http://releases.k8s.io).
|
||||||
|
</strong>
|
||||||
|
--
|
||||||
|
|
||||||
|
<!-- END STRIP_FOR_RELEASE -->
|
||||||
|
|
||||||
|
<!-- END MUNGE: UNVERSIONED_WARNING -->
|
||||||
|
|
||||||
|
# How to Use it?
|
||||||
|
|
||||||
|
Install *cifs-utils* on the Kubernetes host. For example, on Fedora based Linux
|
||||||
|
|
||||||
|
# yum -y install cifs-utils
|
||||||
|
|
||||||
|
Note, as explained in [Azure File Storage for Linux](https://azure.microsoft.com/en-us/documentation/articles/storage-how-to-use-files-linux/), the Linux hosts and the file share must be in the same Azure region.
|
||||||
|
|
||||||
|
Obtain an Microsoft Azure storage account and create a [secret](secret/azure-secret.yaml) that contains the base64 encoded Azure Storage account name and key. In the secret file, base64-encode Azure Storage account name and pair it with name *azurestorageaccountname*, and base64-encode Azure Storage access key and pair it with name *azurestorageaccountkey*.
|
||||||
|
|
||||||
|
Then create a Pod using the volume spec based on [azure](azure.yaml).
|
||||||
|
|
||||||
|
In the pod, you need to provide the following information:
|
||||||
|
|
||||||
|
- *secretName*: the name of the secret that contains both Azure storage account name and key.
|
||||||
|
- *shareName*: The share name to be used.
|
||||||
|
- *readOnly*: Whether the filesystem is used as readOnly.
|
||||||
|
|
||||||
|
Create the secret:
|
||||||
|
|
||||||
|
```console
|
||||||
|
# kubectl create -f examples/azure_file/secret/azure-secret.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
You should see the account name and key from `kubectl get secret`
|
||||||
|
|
||||||
|
Then create the Pod:
|
||||||
|
|
||||||
|
```console
|
||||||
|
# kubectl create -f examples/azure_file/azure.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
|
[]()
|
||||||
|
<!-- END MUNGE: GENERATED_ANALYTICS -->
|
17
examples/azure_file/azure.yaml
Normal file
17
examples/azure_file/azure.yaml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: azure
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: kubernetes/pause
|
||||||
|
name: azure
|
||||||
|
volumeMounts:
|
||||||
|
- name: azure
|
||||||
|
mountPath: /mnt/azure
|
||||||
|
volumes:
|
||||||
|
- name: azure
|
||||||
|
azureFile:
|
||||||
|
secretName: azure-secret
|
||||||
|
shareName: k8stest
|
||||||
|
readOnly: false
|
8
examples/azure_file/secret/azure-secret.yaml
Normal file
8
examples/azure_file/secret/azure-secret.yaml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: azure-secret
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
azurestorageaccountname: azhzdGVzdA==
|
||||||
|
azurestorageaccountkey: eElGMXpKYm5ub2pGTE1Ta0JwNTBteDAyckhzTUsyc2pVN21GdDRMMTNob0I3ZHJBYUo4akQ2K0E0NDNqSm9nVjd5MkZVT2hRQ1dQbU02WWFOSHk3cWc9PQ==
|
@ -402,6 +402,9 @@ func TestExampleObjectSchemas(t *testing.T) {
|
|||||||
"redis-service": &api.Service{},
|
"redis-service": &api.Service{},
|
||||||
"job": &extensions.Job{},
|
"job": &extensions.Job{},
|
||||||
},
|
},
|
||||||
|
"../examples/azure_file": {
|
||||||
|
"azure": &api.Pod{},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
capabilities.SetForTests(capabilities.Capabilities{
|
capabilities.SetForTests(capabilities.Capabilities{
|
||||||
|
@ -33,6 +33,7 @@ func init() {
|
|||||||
if err := Scheme.AddGeneratedDeepCopyFuncs(
|
if err := Scheme.AddGeneratedDeepCopyFuncs(
|
||||||
DeepCopy_api_AWSElasticBlockStoreVolumeSource,
|
DeepCopy_api_AWSElasticBlockStoreVolumeSource,
|
||||||
DeepCopy_api_Affinity,
|
DeepCopy_api_Affinity,
|
||||||
|
DeepCopy_api_AzureFileVolumeSource,
|
||||||
DeepCopy_api_Binding,
|
DeepCopy_api_Binding,
|
||||||
DeepCopy_api_Capabilities,
|
DeepCopy_api_Capabilities,
|
||||||
DeepCopy_api_CephFSVolumeSource,
|
DeepCopy_api_CephFSVolumeSource,
|
||||||
@ -203,6 +204,13 @@ func DeepCopy_api_Affinity(in Affinity, out *Affinity, c *conversion.Cloner) err
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DeepCopy_api_AzureFileVolumeSource(in AzureFileVolumeSource, out *AzureFileVolumeSource, c *conversion.Cloner) error {
|
||||||
|
out.SecretName = in.SecretName
|
||||||
|
out.ShareName = in.ShareName
|
||||||
|
out.ReadOnly = in.ReadOnly
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func DeepCopy_api_Binding(in Binding, out *Binding, c *conversion.Cloner) error {
|
func DeepCopy_api_Binding(in Binding, out *Binding, c *conversion.Cloner) error {
|
||||||
if err := DeepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
|
if err := DeepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -1828,6 +1836,15 @@ func DeepCopy_api_PersistentVolumeSource(in PersistentVolumeSource, out *Persist
|
|||||||
} else {
|
} else {
|
||||||
out.Flocker = nil
|
out.Flocker = nil
|
||||||
}
|
}
|
||||||
|
if in.AzureFile != nil {
|
||||||
|
in, out := in.AzureFile, &out.AzureFile
|
||||||
|
*out = new(AzureFileVolumeSource)
|
||||||
|
if err := DeepCopy_api_AzureFileVolumeSource(*in, *out, c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.AzureFile = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2912,6 +2929,15 @@ func DeepCopy_api_VolumeSource(in VolumeSource, out *VolumeSource, c *conversion
|
|||||||
} else {
|
} else {
|
||||||
out.FC = nil
|
out.FC = nil
|
||||||
}
|
}
|
||||||
|
if in.AzureFile != nil {
|
||||||
|
in, out := in.AzureFile, &out.AzureFile
|
||||||
|
*out = new(AzureFileVolumeSource)
|
||||||
|
if err := DeepCopy_api_AzureFileVolumeSource(*in, *out, c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.AzureFile = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -215,6 +215,8 @@ type VolumeSource struct {
|
|||||||
DownwardAPI *DownwardAPIVolumeSource `json:"downwardAPI,omitempty"`
|
DownwardAPI *DownwardAPIVolumeSource `json:"downwardAPI,omitempty"`
|
||||||
// FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.
|
// FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.
|
||||||
FC *FCVolumeSource `json:"fc,omitempty"`
|
FC *FCVolumeSource `json:"fc,omitempty"`
|
||||||
|
// AzureFile represents an Azure File Service mount on the host and bind mount to the pod.
|
||||||
|
AzureFile *AzureFileVolumeSource `json:"azureFile,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Similar to VolumeSource but meant for the administrator who creates PVs.
|
// Similar to VolumeSource but meant for the administrator who creates PVs.
|
||||||
@ -251,6 +253,8 @@ type PersistentVolumeSource struct {
|
|||||||
FC *FCVolumeSource `json:"fc,omitempty"`
|
FC *FCVolumeSource `json:"fc,omitempty"`
|
||||||
// Flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running
|
// Flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running
|
||||||
Flocker *FlockerVolumeSource `json:"flocker,omitempty"`
|
Flocker *FlockerVolumeSource `json:"flocker,omitempty"`
|
||||||
|
// AzureFile represents an Azure File Service mount on the host and bind mount to the pod.
|
||||||
|
AzureFile *AzureFileVolumeSource `json:"azureFile,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PersistentVolumeClaimVolumeSource struct {
|
type PersistentVolumeClaimVolumeSource struct {
|
||||||
@ -672,6 +676,17 @@ type DownwardAPIVolumeFile struct {
|
|||||||
FieldRef ObjectFieldSelector `json:"fieldRef"`
|
FieldRef ObjectFieldSelector `json:"fieldRef"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AzureFile represents an Azure File Service mount on the host and bind mount to the pod.
|
||||||
|
type AzureFileVolumeSource struct {
|
||||||
|
// the name of secret that contains Azure Storage Account Name and Key
|
||||||
|
SecretName string `json:"secretName"`
|
||||||
|
// Share Name
|
||||||
|
ShareName string `json:"shareName"`
|
||||||
|
// Defaults to false (read/write). ReadOnly here will force
|
||||||
|
// the ReadOnly setting in VolumeMounts.
|
||||||
|
ReadOnly bool `json:"readOnly,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// ContainerPort represents a network port in a single container
|
// ContainerPort represents a network port in a single container
|
||||||
type ContainerPort struct {
|
type ContainerPort struct {
|
||||||
// Optional: If specified, this must be an IANA_SVC_NAME Each named port
|
// Optional: If specified, this must be an IANA_SVC_NAME Each named port
|
||||||
|
@ -43,6 +43,20 @@ func Convert_api_AWSElasticBlockStoreVolumeSource_To_v1_AWSElasticBlockStoreVolu
|
|||||||
return autoConvert_api_AWSElasticBlockStoreVolumeSource_To_v1_AWSElasticBlockStoreVolumeSource(in, out, s)
|
return autoConvert_api_AWSElasticBlockStoreVolumeSource_To_v1_AWSElasticBlockStoreVolumeSource(in, out, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func autoConvert_api_AzureFileVolumeSource_To_v1_AzureFileVolumeSource(in *api.AzureFileVolumeSource, out *AzureFileVolumeSource, s conversion.Scope) error {
|
||||||
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
|
defaulting.(func(*api.AzureFileVolumeSource))(in)
|
||||||
|
}
|
||||||
|
out.SecretName = in.SecretName
|
||||||
|
out.ShareName = in.ShareName
|
||||||
|
out.ReadOnly = in.ReadOnly
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Convert_api_AzureFileVolumeSource_To_v1_AzureFileVolumeSource(in *api.AzureFileVolumeSource, out *AzureFileVolumeSource, s conversion.Scope) error {
|
||||||
|
return autoConvert_api_AzureFileVolumeSource_To_v1_AzureFileVolumeSource(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
func autoConvert_api_Binding_To_v1_Binding(in *api.Binding, out *Binding, s conversion.Scope) error {
|
func autoConvert_api_Binding_To_v1_Binding(in *api.Binding, out *Binding, s conversion.Scope) error {
|
||||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
defaulting.(func(*api.Binding))(in)
|
defaulting.(func(*api.Binding))(in)
|
||||||
@ -1970,6 +1984,15 @@ func autoConvert_api_PersistentVolumeSource_To_v1_PersistentVolumeSource(in *api
|
|||||||
} else {
|
} else {
|
||||||
out.Flocker = nil
|
out.Flocker = nil
|
||||||
}
|
}
|
||||||
|
// unable to generate simple pointer conversion for api.AzureFileVolumeSource -> v1.AzureFileVolumeSource
|
||||||
|
if in.AzureFile != nil {
|
||||||
|
out.AzureFile = new(AzureFileVolumeSource)
|
||||||
|
if err := Convert_api_AzureFileVolumeSource_To_v1_AzureFileVolumeSource(in.AzureFile, out.AzureFile, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.AzureFile = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3196,6 +3219,15 @@ func autoConvert_api_VolumeSource_To_v1_VolumeSource(in *api.VolumeSource, out *
|
|||||||
} else {
|
} else {
|
||||||
out.FC = nil
|
out.FC = nil
|
||||||
}
|
}
|
||||||
|
// unable to generate simple pointer conversion for api.AzureFileVolumeSource -> v1.AzureFileVolumeSource
|
||||||
|
if in.AzureFile != nil {
|
||||||
|
out.AzureFile = new(AzureFileVolumeSource)
|
||||||
|
if err := Convert_api_AzureFileVolumeSource_To_v1_AzureFileVolumeSource(in.AzureFile, out.AzureFile, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.AzureFile = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3231,6 +3263,20 @@ func Convert_v1_AWSElasticBlockStoreVolumeSource_To_api_AWSElasticBlockStoreVolu
|
|||||||
return autoConvert_v1_AWSElasticBlockStoreVolumeSource_To_api_AWSElasticBlockStoreVolumeSource(in, out, s)
|
return autoConvert_v1_AWSElasticBlockStoreVolumeSource_To_api_AWSElasticBlockStoreVolumeSource(in, out, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func autoConvert_v1_AzureFileVolumeSource_To_api_AzureFileVolumeSource(in *AzureFileVolumeSource, out *api.AzureFileVolumeSource, s conversion.Scope) error {
|
||||||
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
|
defaulting.(func(*AzureFileVolumeSource))(in)
|
||||||
|
}
|
||||||
|
out.SecretName = in.SecretName
|
||||||
|
out.ShareName = in.ShareName
|
||||||
|
out.ReadOnly = in.ReadOnly
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Convert_v1_AzureFileVolumeSource_To_api_AzureFileVolumeSource(in *AzureFileVolumeSource, out *api.AzureFileVolumeSource, s conversion.Scope) error {
|
||||||
|
return autoConvert_v1_AzureFileVolumeSource_To_api_AzureFileVolumeSource(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
func autoConvert_v1_Binding_To_api_Binding(in *Binding, out *api.Binding, s conversion.Scope) error {
|
func autoConvert_v1_Binding_To_api_Binding(in *Binding, out *api.Binding, s conversion.Scope) error {
|
||||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
defaulting.(func(*Binding))(in)
|
defaulting.(func(*Binding))(in)
|
||||||
@ -5099,6 +5145,15 @@ func autoConvert_v1_PersistentVolumeSource_To_api_PersistentVolumeSource(in *Per
|
|||||||
} else {
|
} else {
|
||||||
out.FlexVolume = nil
|
out.FlexVolume = nil
|
||||||
}
|
}
|
||||||
|
// unable to generate simple pointer conversion for v1.AzureFileVolumeSource -> api.AzureFileVolumeSource
|
||||||
|
if in.AzureFile != nil {
|
||||||
|
out.AzureFile = new(api.AzureFileVolumeSource)
|
||||||
|
if err := Convert_v1_AzureFileVolumeSource_To_api_AzureFileVolumeSource(in.AzureFile, out.AzureFile, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.AzureFile = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6274,6 +6329,15 @@ func autoConvert_v1_VolumeSource_To_api_VolumeSource(in *VolumeSource, out *api.
|
|||||||
} else {
|
} else {
|
||||||
out.FC = nil
|
out.FC = nil
|
||||||
}
|
}
|
||||||
|
// unable to generate simple pointer conversion for v1.AzureFileVolumeSource -> api.AzureFileVolumeSource
|
||||||
|
if in.AzureFile != nil {
|
||||||
|
out.AzureFile = new(api.AzureFileVolumeSource)
|
||||||
|
if err := Convert_v1_AzureFileVolumeSource_To_api_AzureFileVolumeSource(in.AzureFile, out.AzureFile, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.AzureFile = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6284,6 +6348,7 @@ func Convert_v1_VolumeSource_To_api_VolumeSource(in *VolumeSource, out *api.Volu
|
|||||||
func init() {
|
func init() {
|
||||||
err := api.Scheme.AddGeneratedConversionFuncs(
|
err := api.Scheme.AddGeneratedConversionFuncs(
|
||||||
autoConvert_api_AWSElasticBlockStoreVolumeSource_To_v1_AWSElasticBlockStoreVolumeSource,
|
autoConvert_api_AWSElasticBlockStoreVolumeSource_To_v1_AWSElasticBlockStoreVolumeSource,
|
||||||
|
autoConvert_api_AzureFileVolumeSource_To_v1_AzureFileVolumeSource,
|
||||||
autoConvert_api_Binding_To_v1_Binding,
|
autoConvert_api_Binding_To_v1_Binding,
|
||||||
autoConvert_api_Capabilities_To_v1_Capabilities,
|
autoConvert_api_Capabilities_To_v1_Capabilities,
|
||||||
autoConvert_api_CephFSVolumeSource_To_v1_CephFSVolumeSource,
|
autoConvert_api_CephFSVolumeSource_To_v1_CephFSVolumeSource,
|
||||||
@ -6410,6 +6475,7 @@ func init() {
|
|||||||
autoConvert_api_Volume_To_v1_Volume,
|
autoConvert_api_Volume_To_v1_Volume,
|
||||||
autoConvert_unversioned_ExportOptions_To_v1_ExportOptions,
|
autoConvert_unversioned_ExportOptions_To_v1_ExportOptions,
|
||||||
autoConvert_v1_AWSElasticBlockStoreVolumeSource_To_api_AWSElasticBlockStoreVolumeSource,
|
autoConvert_v1_AWSElasticBlockStoreVolumeSource_To_api_AWSElasticBlockStoreVolumeSource,
|
||||||
|
autoConvert_v1_AzureFileVolumeSource_To_api_AzureFileVolumeSource,
|
||||||
autoConvert_v1_Binding_To_api_Binding,
|
autoConvert_v1_Binding_To_api_Binding,
|
||||||
autoConvert_v1_Capabilities_To_api_Capabilities,
|
autoConvert_v1_Capabilities_To_api_Capabilities,
|
||||||
autoConvert_v1_CephFSVolumeSource_To_api_CephFSVolumeSource,
|
autoConvert_v1_CephFSVolumeSource_To_api_CephFSVolumeSource,
|
||||||
|
@ -73,6 +73,13 @@ func deepCopy_v1_AWSElasticBlockStoreVolumeSource(in AWSElasticBlockStoreVolumeS
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func deepCopy_v1_AzureFileVolumeSource(in AzureFileVolumeSource, out *AzureFileVolumeSource, c *conversion.Cloner) error {
|
||||||
|
out.SecretName = in.SecretName
|
||||||
|
out.ShareName = in.ShareName
|
||||||
|
out.ReadOnly = in.ReadOnly
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func deepCopy_v1_Binding(in Binding, out *Binding, c *conversion.Cloner) error {
|
func deepCopy_v1_Binding(in Binding, out *Binding, c *conversion.Cloner) error {
|
||||||
if err := deepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
|
if err := deepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -1490,6 +1497,14 @@ func deepCopy_v1_PersistentVolumeSource(in PersistentVolumeSource, out *Persiste
|
|||||||
} else {
|
} else {
|
||||||
out.FlexVolume = nil
|
out.FlexVolume = nil
|
||||||
}
|
}
|
||||||
|
if in.AzureFile != nil {
|
||||||
|
out.AzureFile = new(AzureFileVolumeSource)
|
||||||
|
if err := deepCopy_v1_AzureFileVolumeSource(*in.AzureFile, out.AzureFile, c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.AzureFile = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2514,6 +2529,14 @@ func deepCopy_v1_VolumeSource(in VolumeSource, out *VolumeSource, c *conversion.
|
|||||||
} else {
|
} else {
|
||||||
out.FC = nil
|
out.FC = nil
|
||||||
}
|
}
|
||||||
|
if in.AzureFile != nil {
|
||||||
|
out.AzureFile = new(AzureFileVolumeSource)
|
||||||
|
if err := deepCopy_v1_AzureFileVolumeSource(*in.AzureFile, out.AzureFile, c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.AzureFile = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2550,6 +2573,7 @@ func init() {
|
|||||||
deepCopy_unversioned_Time,
|
deepCopy_unversioned_Time,
|
||||||
deepCopy_unversioned_TypeMeta,
|
deepCopy_unversioned_TypeMeta,
|
||||||
deepCopy_v1_AWSElasticBlockStoreVolumeSource,
|
deepCopy_v1_AWSElasticBlockStoreVolumeSource,
|
||||||
|
deepCopy_v1_AzureFileVolumeSource,
|
||||||
deepCopy_v1_Binding,
|
deepCopy_v1_Binding,
|
||||||
deepCopy_v1_Capabilities,
|
deepCopy_v1_Capabilities,
|
||||||
deepCopy_v1_CephFSVolumeSource,
|
deepCopy_v1_CephFSVolumeSource,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -261,6 +261,8 @@ type VolumeSource struct {
|
|||||||
DownwardAPI *DownwardAPIVolumeSource `json:"downwardAPI,omitempty"`
|
DownwardAPI *DownwardAPIVolumeSource `json:"downwardAPI,omitempty"`
|
||||||
// FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.
|
// FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.
|
||||||
FC *FCVolumeSource `json:"fc,omitempty"`
|
FC *FCVolumeSource `json:"fc,omitempty"`
|
||||||
|
// AzureFile represents an Azure File Service mount on the host and bind mount to the pod.
|
||||||
|
AzureFile *AzureFileVolumeSource `json:"azureFile,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PersistentVolumeClaimVolumeSource references the user's PVC in the same namespace.
|
// PersistentVolumeClaimVolumeSource references the user's PVC in the same namespace.
|
||||||
@ -319,6 +321,8 @@ type PersistentVolumeSource struct {
|
|||||||
// provisioned/attached using a exec based plugin. This is an
|
// provisioned/attached using a exec based plugin. This is an
|
||||||
// alpha feature and may change in future.
|
// alpha feature and may change in future.
|
||||||
FlexVolume *FlexVolumeSource `json:"flexVolume,omitempty"`
|
FlexVolume *FlexVolumeSource `json:"flexVolume,omitempty"`
|
||||||
|
// AzureFile represents an Azure File Service mount on the host and bind mount to the pod.
|
||||||
|
AzureFile *AzureFileVolumeSource `json:"azureFile,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PersistentVolume (PV) is a storage resource provisioned by an administrator.
|
// PersistentVolume (PV) is a storage resource provisioned by an administrator.
|
||||||
@ -791,6 +795,17 @@ type FCVolumeSource struct {
|
|||||||
ReadOnly bool `json:"readOnly,omitempty"`
|
ReadOnly bool `json:"readOnly,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AzureFile represents an Azure File Service mount on the host and bind mount to the pod.
|
||||||
|
type AzureFileVolumeSource struct {
|
||||||
|
// the name of secret that contains Azure Storage Account Name and Key
|
||||||
|
SecretName string `json:"secretName"`
|
||||||
|
// Share Name
|
||||||
|
ShareName string `json:"shareName"`
|
||||||
|
// Defaults to false (read/write). ReadOnly here will force
|
||||||
|
// the ReadOnly setting in VolumeMounts.
|
||||||
|
ReadOnly bool `json:"readOnly,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// ContainerPort represents a network port in a single container.
|
// ContainerPort represents a network port in a single container.
|
||||||
type ContainerPort struct {
|
type ContainerPort struct {
|
||||||
// If specified, this must be an IANA_SVC_NAME and unique within the pod. Each
|
// If specified, this must be an IANA_SVC_NAME and unique within the pod. Each
|
||||||
|
@ -48,6 +48,17 @@ func (Affinity) SwaggerDoc() map[string]string {
|
|||||||
return map_Affinity
|
return map_Affinity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var map_AzureFileVolumeSource = map[string]string{
|
||||||
|
"": "AzureFile represents an Azure File Service mount on the host and bind mount to the pod.",
|
||||||
|
"secretName": "the name of secret that contains Azure Storage Account Name and Key",
|
||||||
|
"shareName": "Share Name",
|
||||||
|
"readOnly": "Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts.",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (AzureFileVolumeSource) SwaggerDoc() map[string]string {
|
||||||
|
return map_AzureFileVolumeSource
|
||||||
|
}
|
||||||
|
|
||||||
var map_Binding = map[string]string{
|
var map_Binding = map[string]string{
|
||||||
"": "Binding ties one object to another. For example, a pod is bound to a node by a scheduler.",
|
"": "Binding ties one object to another. For example, a pod is bound to a node by a scheduler.",
|
||||||
"metadata": "Standard object's metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata",
|
"metadata": "Standard object's metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata",
|
||||||
@ -990,6 +1001,7 @@ var map_PersistentVolumeSource = map[string]string{
|
|||||||
"fc": "FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.",
|
"fc": "FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.",
|
||||||
"flocker": "Flocker represents a Flocker volume attached to a kubelet's host machine and exposed to the pod for its usage. This depends on the Flocker control service being running",
|
"flocker": "Flocker represents a Flocker volume attached to a kubelet's host machine and exposed to the pod for its usage. This depends on the Flocker control service being running",
|
||||||
"flexVolume": "FlexVolume represents a generic volume resource that is provisioned/attached using a exec based plugin. This is an alpha feature and may change in future.",
|
"flexVolume": "FlexVolume represents a generic volume resource that is provisioned/attached using a exec based plugin. This is an alpha feature and may change in future.",
|
||||||
|
"azureFile": "AzureFile represents an Azure File Service mount on the host and bind mount to the pod.",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (PersistentVolumeSource) SwaggerDoc() map[string]string {
|
func (PersistentVolumeSource) SwaggerDoc() map[string]string {
|
||||||
@ -1541,6 +1553,7 @@ var map_VolumeSource = map[string]string{
|
|||||||
"flocker": "Flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running",
|
"flocker": "Flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running",
|
||||||
"downwardAPI": "DownwardAPI represents downward API about the pod that should populate this volume",
|
"downwardAPI": "DownwardAPI represents downward API about the pod that should populate this volume",
|
||||||
"fc": "FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.",
|
"fc": "FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.",
|
||||||
|
"azureFile": "AzureFile represents an Azure File Service mount on the host and bind mount to the pod.",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (VolumeSource) SwaggerDoc() map[string]string {
|
func (VolumeSource) SwaggerDoc() map[string]string {
|
||||||
|
@ -494,6 +494,10 @@ func validateVolumeSource(source *api.VolumeSource, fldPath *field.Path) field.E
|
|||||||
numVolumes++
|
numVolumes++
|
||||||
allErrs = append(allErrs, validateFlexVolumeSource(source.FlexVolume, fldPath.Child("flexVolume"))...)
|
allErrs = append(allErrs, validateFlexVolumeSource(source.FlexVolume, fldPath.Child("flexVolume"))...)
|
||||||
}
|
}
|
||||||
|
if source.AzureFile != nil {
|
||||||
|
numVolumes++
|
||||||
|
allErrs = append(allErrs, validateAzureFile(source.AzureFile, fldPath.Child("azureFile"))...)
|
||||||
|
}
|
||||||
if numVolumes == 0 {
|
if numVolumes == 0 {
|
||||||
allErrs = append(allErrs, field.Required(fldPath, "must specify a volume type"))
|
allErrs = append(allErrs, field.Required(fldPath, "must specify a volume type"))
|
||||||
}
|
}
|
||||||
@ -718,6 +722,17 @@ func validateFlexVolumeSource(fv *api.FlexVolumeSource, fldPath *field.Path) fie
|
|||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateAzureFile(azure *api.AzureFileVolumeSource, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
if azure.SecretName == "" {
|
||||||
|
allErrs = append(allErrs, field.Required(fldPath.Child("secretName"), ""))
|
||||||
|
}
|
||||||
|
if azure.ShareName == "" {
|
||||||
|
allErrs = append(allErrs, field.Required(fldPath.Child("shareName"), ""))
|
||||||
|
}
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
func ValidatePersistentVolumeName(name string, prefix bool) (bool, string) {
|
func ValidatePersistentVolumeName(name string, prefix bool) (bool, string) {
|
||||||
return NameIsDNSSubdomain(name, prefix)
|
return NameIsDNSSubdomain(name, prefix)
|
||||||
}
|
}
|
||||||
@ -842,6 +857,10 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) field.ErrorList {
|
|||||||
numVolumes++
|
numVolumes++
|
||||||
allErrs = append(allErrs, validateFlexVolumeSource(pv.Spec.FlexVolume, specPath.Child("flexVolume"))...)
|
allErrs = append(allErrs, validateFlexVolumeSource(pv.Spec.FlexVolume, specPath.Child("flexVolume"))...)
|
||||||
}
|
}
|
||||||
|
if pv.Spec.AzureFile != nil {
|
||||||
|
numVolumes++
|
||||||
|
allErrs = append(allErrs, validateAzureFile(pv.Spec.AzureFile, specPath.Child("azureFile"))...)
|
||||||
|
}
|
||||||
if numVolumes == 0 {
|
if numVolumes == 0 {
|
||||||
allErrs = append(allErrs, field.Required(specPath, "must specify a volume type"))
|
allErrs = append(allErrs, field.Required(specPath, "must specify a volume type"))
|
||||||
}
|
}
|
||||||
|
@ -509,6 +509,7 @@ func TestValidateVolumes(t *testing.T) {
|
|||||||
}}}},
|
}}}},
|
||||||
{Name: "fc", VolumeSource: api.VolumeSource{FC: &api.FCVolumeSource{[]string{"some_wwn"}, &lun, "ext4", false}}},
|
{Name: "fc", VolumeSource: api.VolumeSource{FC: &api.FCVolumeSource{[]string{"some_wwn"}, &lun, "ext4", false}}},
|
||||||
{Name: "flexvolume", VolumeSource: api.VolumeSource{FlexVolume: &api.FlexVolumeSource{Driver: "kubernetes.io/blue", FSType: "ext4"}}},
|
{Name: "flexvolume", VolumeSource: api.VolumeSource{FlexVolume: &api.FlexVolumeSource{Driver: "kubernetes.io/blue", FSType: "ext4"}}},
|
||||||
|
{Name: "azure", VolumeSource: api.VolumeSource{AzureFile: &api.AzureFileVolumeSource{"key", "share", false}}},
|
||||||
}
|
}
|
||||||
names, errs := validateVolumes(successCase, field.NewPath("field"))
|
names, errs := validateVolumes(successCase, field.NewPath("field"))
|
||||||
if len(errs) != 0 {
|
if len(errs) != 0 {
|
||||||
@ -557,6 +558,8 @@ func TestValidateVolumes(t *testing.T) {
|
|||||||
zeroWWN := api.VolumeSource{FC: &api.FCVolumeSource{[]string{}, &lun, "ext4", false}}
|
zeroWWN := api.VolumeSource{FC: &api.FCVolumeSource{[]string{}, &lun, "ext4", false}}
|
||||||
emptyLun := api.VolumeSource{FC: &api.FCVolumeSource{[]string{"wwn"}, nil, "ext4", false}}
|
emptyLun := api.VolumeSource{FC: &api.FCVolumeSource{[]string{"wwn"}, nil, "ext4", false}}
|
||||||
slashInName := api.VolumeSource{Flocker: &api.FlockerVolumeSource{DatasetName: "foo/bar"}}
|
slashInName := api.VolumeSource{Flocker: &api.FlockerVolumeSource{DatasetName: "foo/bar"}}
|
||||||
|
emptyAzureSecret := api.VolumeSource{AzureFile: &api.AzureFileVolumeSource{"", "share", false}}
|
||||||
|
emptyAzureShare := api.VolumeSource{AzureFile: &api.AzureFileVolumeSource{"name", "", false}}
|
||||||
errorCases := map[string]struct {
|
errorCases := map[string]struct {
|
||||||
V []api.Volume
|
V []api.Volume
|
||||||
T field.ErrorType
|
T field.ErrorType
|
||||||
@ -678,6 +681,16 @@ func TestValidateVolumes(t *testing.T) {
|
|||||||
field.ErrorTypeInvalid,
|
field.ErrorTypeInvalid,
|
||||||
"gitRepo.directory", "",
|
"gitRepo.directory", "",
|
||||||
},
|
},
|
||||||
|
"empty secret": {
|
||||||
|
[]api.Volume{{Name: "emptyaccount", VolumeSource: emptyAzureSecret}},
|
||||||
|
field.ErrorTypeRequired,
|
||||||
|
"azureFile.secretName", "",
|
||||||
|
},
|
||||||
|
"empty share": {
|
||||||
|
[]api.Volume{{Name: "emptyaccount", VolumeSource: emptyAzureShare}},
|
||||||
|
field.ErrorTypeRequired,
|
||||||
|
"azureFile.shareName", "",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for k, v := range errorCases {
|
for k, v := range errorCases {
|
||||||
_, errs := validateVolumes(v.V, field.NewPath("field"))
|
_, errs := validateVolumes(v.V, field.NewPath("field"))
|
||||||
|
@ -44,6 +44,20 @@ func Convert_api_AWSElasticBlockStoreVolumeSource_To_v1_AWSElasticBlockStoreVolu
|
|||||||
return autoConvert_api_AWSElasticBlockStoreVolumeSource_To_v1_AWSElasticBlockStoreVolumeSource(in, out, s)
|
return autoConvert_api_AWSElasticBlockStoreVolumeSource_To_v1_AWSElasticBlockStoreVolumeSource(in, out, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func autoConvert_api_AzureFileVolumeSource_To_v1_AzureFileVolumeSource(in *api.AzureFileVolumeSource, out *v1.AzureFileVolumeSource, s conversion.Scope) error {
|
||||||
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
|
defaulting.(func(*api.AzureFileVolumeSource))(in)
|
||||||
|
}
|
||||||
|
out.SecretName = in.SecretName
|
||||||
|
out.ShareName = in.ShareName
|
||||||
|
out.ReadOnly = in.ReadOnly
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Convert_api_AzureFileVolumeSource_To_v1_AzureFileVolumeSource(in *api.AzureFileVolumeSource, out *v1.AzureFileVolumeSource, s conversion.Scope) error {
|
||||||
|
return autoConvert_api_AzureFileVolumeSource_To_v1_AzureFileVolumeSource(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
func autoConvert_api_Capabilities_To_v1_Capabilities(in *api.Capabilities, out *v1.Capabilities, s conversion.Scope) error {
|
func autoConvert_api_Capabilities_To_v1_Capabilities(in *api.Capabilities, out *v1.Capabilities, s conversion.Scope) error {
|
||||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
defaulting.(func(*api.Capabilities))(in)
|
defaulting.(func(*api.Capabilities))(in)
|
||||||
@ -1257,6 +1271,15 @@ func autoConvert_api_VolumeSource_To_v1_VolumeSource(in *api.VolumeSource, out *
|
|||||||
} else {
|
} else {
|
||||||
out.FC = nil
|
out.FC = nil
|
||||||
}
|
}
|
||||||
|
// unable to generate simple pointer conversion for api.AzureFileVolumeSource -> v1.AzureFileVolumeSource
|
||||||
|
if in.AzureFile != nil {
|
||||||
|
out.AzureFile = new(v1.AzureFileVolumeSource)
|
||||||
|
if err := Convert_api_AzureFileVolumeSource_To_v1_AzureFileVolumeSource(in.AzureFile, out.AzureFile, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.AzureFile = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1329,6 +1352,20 @@ func Convert_v1_AWSElasticBlockStoreVolumeSource_To_api_AWSElasticBlockStoreVolu
|
|||||||
return autoConvert_v1_AWSElasticBlockStoreVolumeSource_To_api_AWSElasticBlockStoreVolumeSource(in, out, s)
|
return autoConvert_v1_AWSElasticBlockStoreVolumeSource_To_api_AWSElasticBlockStoreVolumeSource(in, out, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func autoConvert_v1_AzureFileVolumeSource_To_api_AzureFileVolumeSource(in *v1.AzureFileVolumeSource, out *api.AzureFileVolumeSource, s conversion.Scope) error {
|
||||||
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
|
defaulting.(func(*v1.AzureFileVolumeSource))(in)
|
||||||
|
}
|
||||||
|
out.SecretName = in.SecretName
|
||||||
|
out.ShareName = in.ShareName
|
||||||
|
out.ReadOnly = in.ReadOnly
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Convert_v1_AzureFileVolumeSource_To_api_AzureFileVolumeSource(in *v1.AzureFileVolumeSource, out *api.AzureFileVolumeSource, s conversion.Scope) error {
|
||||||
|
return autoConvert_v1_AzureFileVolumeSource_To_api_AzureFileVolumeSource(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
func autoConvert_v1_Capabilities_To_api_Capabilities(in *v1.Capabilities, out *api.Capabilities, s conversion.Scope) error {
|
func autoConvert_v1_Capabilities_To_api_Capabilities(in *v1.Capabilities, out *api.Capabilities, s conversion.Scope) error {
|
||||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
defaulting.(func(*v1.Capabilities))(in)
|
defaulting.(func(*v1.Capabilities))(in)
|
||||||
@ -2518,6 +2555,15 @@ func autoConvert_v1_VolumeSource_To_api_VolumeSource(in *v1.VolumeSource, out *a
|
|||||||
} else {
|
} else {
|
||||||
out.FC = nil
|
out.FC = nil
|
||||||
}
|
}
|
||||||
|
// unable to generate simple pointer conversion for v1.AzureFileVolumeSource -> api.AzureFileVolumeSource
|
||||||
|
if in.AzureFile != nil {
|
||||||
|
out.AzureFile = new(api.AzureFileVolumeSource)
|
||||||
|
if err := Convert_v1_AzureFileVolumeSource_To_api_AzureFileVolumeSource(in.AzureFile, out.AzureFile, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.AzureFile = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5213,6 +5259,7 @@ func Convert_v1beta1_ThirdPartyResourceList_To_extensions_ThirdPartyResourceList
|
|||||||
func init() {
|
func init() {
|
||||||
err := api.Scheme.AddGeneratedConversionFuncs(
|
err := api.Scheme.AddGeneratedConversionFuncs(
|
||||||
autoConvert_api_AWSElasticBlockStoreVolumeSource_To_v1_AWSElasticBlockStoreVolumeSource,
|
autoConvert_api_AWSElasticBlockStoreVolumeSource_To_v1_AWSElasticBlockStoreVolumeSource,
|
||||||
|
autoConvert_api_AzureFileVolumeSource_To_v1_AzureFileVolumeSource,
|
||||||
autoConvert_api_Capabilities_To_v1_Capabilities,
|
autoConvert_api_Capabilities_To_v1_Capabilities,
|
||||||
autoConvert_api_CephFSVolumeSource_To_v1_CephFSVolumeSource,
|
autoConvert_api_CephFSVolumeSource_To_v1_CephFSVolumeSource,
|
||||||
autoConvert_api_CinderVolumeSource_To_v1_CinderVolumeSource,
|
autoConvert_api_CinderVolumeSource_To_v1_CinderVolumeSource,
|
||||||
@ -5320,6 +5367,7 @@ func init() {
|
|||||||
autoConvert_unversioned_LabelSelectorRequirement_To_v1beta1_LabelSelectorRequirement,
|
autoConvert_unversioned_LabelSelectorRequirement_To_v1beta1_LabelSelectorRequirement,
|
||||||
autoConvert_unversioned_LabelSelector_To_v1beta1_LabelSelector,
|
autoConvert_unversioned_LabelSelector_To_v1beta1_LabelSelector,
|
||||||
autoConvert_v1_AWSElasticBlockStoreVolumeSource_To_api_AWSElasticBlockStoreVolumeSource,
|
autoConvert_v1_AWSElasticBlockStoreVolumeSource_To_api_AWSElasticBlockStoreVolumeSource,
|
||||||
|
autoConvert_v1_AzureFileVolumeSource_To_api_AzureFileVolumeSource,
|
||||||
autoConvert_v1_Capabilities_To_api_Capabilities,
|
autoConvert_v1_Capabilities_To_api_Capabilities,
|
||||||
autoConvert_v1_CephFSVolumeSource_To_api_CephFSVolumeSource,
|
autoConvert_v1_CephFSVolumeSource_To_api_CephFSVolumeSource,
|
||||||
autoConvert_v1_CinderVolumeSource_To_api_CinderVolumeSource,
|
autoConvert_v1_CinderVolumeSource_To_api_CinderVolumeSource,
|
||||||
|
@ -73,6 +73,13 @@ func deepCopy_v1_AWSElasticBlockStoreVolumeSource(in v1.AWSElasticBlockStoreVolu
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func deepCopy_v1_AzureFileVolumeSource(in v1.AzureFileVolumeSource, out *v1.AzureFileVolumeSource, c *conversion.Cloner) error {
|
||||||
|
out.SecretName = in.SecretName
|
||||||
|
out.ShareName = in.ShareName
|
||||||
|
out.ReadOnly = in.ReadOnly
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func deepCopy_v1_Capabilities(in v1.Capabilities, out *v1.Capabilities, c *conversion.Cloner) error {
|
func deepCopy_v1_Capabilities(in v1.Capabilities, out *v1.Capabilities, c *conversion.Cloner) error {
|
||||||
if in.Add != nil {
|
if in.Add != nil {
|
||||||
out.Add = make([]v1.Capability, len(in.Add))
|
out.Add = make([]v1.Capability, len(in.Add))
|
||||||
@ -964,6 +971,14 @@ func deepCopy_v1_VolumeSource(in v1.VolumeSource, out *v1.VolumeSource, c *conve
|
|||||||
} else {
|
} else {
|
||||||
out.FC = nil
|
out.FC = nil
|
||||||
}
|
}
|
||||||
|
if in.AzureFile != nil {
|
||||||
|
out.AzureFile = new(v1.AzureFileVolumeSource)
|
||||||
|
if err := deepCopy_v1_AzureFileVolumeSource(*in.AzureFile, out.AzureFile, c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.AzureFile = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1981,6 +1996,7 @@ func init() {
|
|||||||
deepCopy_unversioned_Time,
|
deepCopy_unversioned_Time,
|
||||||
deepCopy_unversioned_TypeMeta,
|
deepCopy_unversioned_TypeMeta,
|
||||||
deepCopy_v1_AWSElasticBlockStoreVolumeSource,
|
deepCopy_v1_AWSElasticBlockStoreVolumeSource,
|
||||||
|
deepCopy_v1_AzureFileVolumeSource,
|
||||||
deepCopy_v1_Capabilities,
|
deepCopy_v1_Capabilities,
|
||||||
deepCopy_v1_CephFSVolumeSource,
|
deepCopy_v1_CephFSVolumeSource,
|
||||||
deepCopy_v1_CinderVolumeSource,
|
deepCopy_v1_CinderVolumeSource,
|
||||||
|
234
pkg/volume/azure_file/azure_file.go
Normal file
234
pkg/volume/azure_file/azure_file.go
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
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 azure_file
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
"k8s.io/kubernetes/pkg/types"
|
||||||
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
|
"k8s.io/kubernetes/pkg/util/strings"
|
||||||
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This is the primary entrypoint for volume plugins.
|
||||||
|
func ProbeVolumePlugins() []volume.VolumePlugin {
|
||||||
|
return []volume.VolumePlugin{&azureFilePlugin{nil}}
|
||||||
|
}
|
||||||
|
|
||||||
|
type azureFilePlugin struct {
|
||||||
|
host volume.VolumeHost
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ volume.VolumePlugin = &azureFilePlugin{}
|
||||||
|
var _ volume.PersistentVolumePlugin = &azureFilePlugin{}
|
||||||
|
|
||||||
|
const (
|
||||||
|
azureFilePluginName = "kubernetes.io/azure-file"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (plugin *azureFilePlugin) Init(host volume.VolumeHost) error {
|
||||||
|
plugin.host = host
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (plugin *azureFilePlugin) Name() string {
|
||||||
|
return azureFilePluginName
|
||||||
|
}
|
||||||
|
|
||||||
|
func (plugin *azureFilePlugin) CanSupport(spec *volume.Spec) bool {
|
||||||
|
//TODO: check if mount.cifs is there
|
||||||
|
return (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.AzureFile != nil) ||
|
||||||
|
(spec.Volume != nil && spec.Volume.AzureFile != nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (plugin *azureFilePlugin) GetAccessModes() []api.PersistentVolumeAccessMode {
|
||||||
|
return []api.PersistentVolumeAccessMode{
|
||||||
|
api.ReadWriteOnce,
|
||||||
|
api.ReadOnlyMany,
|
||||||
|
api.ReadWriteMany,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (plugin *azureFilePlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions) (volume.Builder, error) {
|
||||||
|
return plugin.newBuilderInternal(spec, pod, &azureSvc{}, plugin.host.GetMounter())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (plugin *azureFilePlugin) newBuilderInternal(spec *volume.Spec, pod *api.Pod, util azureUtil, mounter mount.Interface) (volume.Builder, error) {
|
||||||
|
var source *api.AzureFileVolumeSource
|
||||||
|
var readOnly bool
|
||||||
|
if spec.Volume != nil && spec.Volume.AzureFile != nil {
|
||||||
|
source = spec.Volume.AzureFile
|
||||||
|
readOnly = spec.Volume.AzureFile.ReadOnly
|
||||||
|
} else {
|
||||||
|
source = spec.PersistentVolume.Spec.AzureFile
|
||||||
|
readOnly = spec.ReadOnly
|
||||||
|
}
|
||||||
|
return &azureFileBuilder{
|
||||||
|
azureFile: &azureFile{
|
||||||
|
volName: spec.Name(),
|
||||||
|
mounter: mounter,
|
||||||
|
pod: pod,
|
||||||
|
plugin: plugin,
|
||||||
|
},
|
||||||
|
util: util,
|
||||||
|
secretName: source.SecretName,
|
||||||
|
shareName: source.ShareName,
|
||||||
|
readOnly: readOnly,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (plugin *azureFilePlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) {
|
||||||
|
return plugin.newCleanerInternal(volName, podUID, plugin.host.GetMounter())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (plugin *azureFilePlugin) newCleanerInternal(volName string, podUID types.UID, mounter mount.Interface) (volume.Cleaner, error) {
|
||||||
|
return &azureFileCleaner{&azureFile{
|
||||||
|
volName: volName,
|
||||||
|
mounter: mounter,
|
||||||
|
pod: &api.Pod{ObjectMeta: api.ObjectMeta{UID: podUID}},
|
||||||
|
plugin: plugin,
|
||||||
|
}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// azureFile volumes represent mount of an AzureFile share.
|
||||||
|
type azureFile struct {
|
||||||
|
volName string
|
||||||
|
pod *api.Pod
|
||||||
|
mounter mount.Interface
|
||||||
|
plugin *azureFilePlugin
|
||||||
|
volume.MetricsNil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (azureFileVolume *azureFile) GetPath() string {
|
||||||
|
name := azureFilePluginName
|
||||||
|
return azureFileVolume.plugin.host.GetPodVolumeDir(azureFileVolume.pod.UID, strings.EscapeQualifiedNameForDisk(name), azureFileVolume.volName)
|
||||||
|
}
|
||||||
|
|
||||||
|
type azureFileBuilder struct {
|
||||||
|
*azureFile
|
||||||
|
util azureUtil
|
||||||
|
secretName string
|
||||||
|
shareName string
|
||||||
|
readOnly bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ volume.Builder = &azureFileBuilder{}
|
||||||
|
|
||||||
|
func (b *azureFileBuilder) GetAttributes() volume.Attributes {
|
||||||
|
return volume.Attributes{
|
||||||
|
ReadOnly: b.readOnly,
|
||||||
|
Managed: !b.readOnly,
|
||||||
|
SupportsSELinux: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUp attaches the disk and bind mounts to the volume path.
|
||||||
|
func (b *azureFileBuilder) SetUp(fsGroup *int64) error {
|
||||||
|
return b.SetUpAt(b.GetPath(), fsGroup)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *azureFileBuilder) SetUpAt(dir string, fsGroup *int64) error {
|
||||||
|
notMnt, err := b.mounter.IsLikelyNotMountPoint(dir)
|
||||||
|
glog.V(4).Infof("AzureFile mount set up: %s %v %v", dir, !notMnt, err)
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !notMnt {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var accountKey, accountName string
|
||||||
|
if accountName, accountKey, err = b.util.GetAzureCredentials(b.plugin.host, b.pod.Namespace, b.secretName, b.shareName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
os.MkdirAll(dir, 0750)
|
||||||
|
source := fmt.Sprintf("//%s.file.core.windows.net/%s", accountName, b.shareName)
|
||||||
|
// parameters suggested by https://azure.microsoft.com/en-us/documentation/articles/storage-how-to-use-files-linux/
|
||||||
|
options := []string{fmt.Sprintf("vers=3.0,username=%s,password=%s,dir_mode=0777,file_mode=0777", accountName, accountKey)}
|
||||||
|
if b.readOnly {
|
||||||
|
options = append(options, "ro")
|
||||||
|
}
|
||||||
|
err = b.mounter.Mount(source, dir, "cifs", options)
|
||||||
|
if err != nil {
|
||||||
|
notMnt, mntErr := b.mounter.IsLikelyNotMountPoint(dir)
|
||||||
|
if mntErr != nil {
|
||||||
|
glog.Errorf("IsLikelyNotMountPoint check failed: %v", mntErr)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !notMnt {
|
||||||
|
if mntErr = b.mounter.Unmount(dir); mntErr != nil {
|
||||||
|
glog.Errorf("Failed to unmount: %v", mntErr)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
notMnt, mntErr := b.mounter.IsLikelyNotMountPoint(dir)
|
||||||
|
if mntErr != nil {
|
||||||
|
glog.Errorf("IsLikelyNotMountPoint check failed: %v", mntErr)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !notMnt {
|
||||||
|
// This is very odd, we don't expect it. We'll try again next sync loop.
|
||||||
|
glog.Errorf("%s is still mounted, despite call to unmount(). Will try again next sync loop.", dir)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os.Remove(dir)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ volume.Cleaner = &azureFileCleaner{}
|
||||||
|
|
||||||
|
type azureFileCleaner struct {
|
||||||
|
*azureFile
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *azureFileCleaner) TearDown() error {
|
||||||
|
return c.TearDownAt(c.GetPath())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *azureFileCleaner) TearDownAt(dir string) error {
|
||||||
|
notMnt, err := c.mounter.IsLikelyNotMountPoint(dir)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("Error checking IsLikelyNotMountPoint: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if notMnt {
|
||||||
|
return os.Remove(dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.mounter.Unmount(dir); err != nil {
|
||||||
|
glog.Errorf("Unmounting failed: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
notMnt, mntErr := c.mounter.IsLikelyNotMountPoint(dir)
|
||||||
|
if mntErr != nil {
|
||||||
|
glog.Errorf("IsLikelyNotMountPoint check failed: %v", mntErr)
|
||||||
|
return mntErr
|
||||||
|
}
|
||||||
|
if notMnt {
|
||||||
|
if err := os.Remove(dir); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
239
pkg/volume/azure_file/azure_file_test.go
Normal file
239
pkg/volume/azure_file/azure_file_test.go
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
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 azure_file
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
"k8s.io/kubernetes/pkg/client/testing/fake"
|
||||||
|
"k8s.io/kubernetes/pkg/types"
|
||||||
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCanSupport(t *testing.T) {
|
||||||
|
tmpDir, err := ioutil.TempDir(os.TempDir(), "azureFileTest")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't make a temp dir: %v", err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
plugMgr := volume.VolumePluginMgr{}
|
||||||
|
plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost(tmpDir, nil, nil))
|
||||||
|
|
||||||
|
plug, err := plugMgr.FindPluginByName("kubernetes.io/azure-file")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Can't find the plugin by name")
|
||||||
|
}
|
||||||
|
if plug.Name() != "kubernetes.io/azure-file" {
|
||||||
|
t.Errorf("Wrong name: %s", plug.Name())
|
||||||
|
}
|
||||||
|
if !plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{AzureFile: &api.AzureFileVolumeSource{}}}}) {
|
||||||
|
t.Errorf("Expected true")
|
||||||
|
}
|
||||||
|
if !plug.CanSupport(&volume.Spec{PersistentVolume: &api.PersistentVolume{Spec: api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{AzureFile: &api.AzureFileVolumeSource{}}}}}) {
|
||||||
|
t.Errorf("Expected true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetAccessModes(t *testing.T) {
|
||||||
|
tmpDir, err := ioutil.TempDir(os.TempDir(), "azureFileTest")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't make a temp dir: %v", err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
plugMgr := volume.VolumePluginMgr{}
|
||||||
|
plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost(tmpDir, nil, nil))
|
||||||
|
|
||||||
|
plug, err := plugMgr.FindPersistentPluginByName("kubernetes.io/azure-file")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Can't find the plugin by name")
|
||||||
|
}
|
||||||
|
if !contains(plug.GetAccessModes(), api.ReadWriteOnce) || !contains(plug.GetAccessModes(), api.ReadOnlyMany) || !contains(plug.GetAccessModes(), api.ReadWriteMany) {
|
||||||
|
t.Errorf("Expected three AccessModeTypes: %s, %s, and %s", api.ReadWriteOnce, api.ReadOnlyMany, api.ReadWriteMany)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func contains(modes []api.PersistentVolumeAccessMode, mode api.PersistentVolumeAccessMode) bool {
|
||||||
|
for _, m := range modes {
|
||||||
|
if m == mode {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPlugin(t *testing.T) {
|
||||||
|
tmpDir, err := ioutil.TempDir(os.TempDir(), "azurefileTest")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't make a temp dir: %v")
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
plugMgr := volume.VolumePluginMgr{}
|
||||||
|
plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost(tmpDir, nil, nil))
|
||||||
|
|
||||||
|
plug, err := plugMgr.FindPluginByName("kubernetes.io/azure-file")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Can't find the plugin by name")
|
||||||
|
}
|
||||||
|
spec := &api.Volume{
|
||||||
|
Name: "vol1",
|
||||||
|
VolumeSource: api.VolumeSource{
|
||||||
|
AzureFile: &api.AzureFileVolumeSource{
|
||||||
|
SecretName: "secret",
|
||||||
|
ShareName: "share",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
fake := &mount.FakeMounter{}
|
||||||
|
pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}}
|
||||||
|
builder, err := plug.(*azureFilePlugin).newBuilderInternal(volume.NewSpecFromVolume(spec), pod, &fakeAzureSvc{}, fake)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to make a new Builder: %v", err)
|
||||||
|
}
|
||||||
|
if builder == nil {
|
||||||
|
t.Errorf("Got a nil Builder")
|
||||||
|
}
|
||||||
|
volPath := path.Join(tmpDir, "pods/poduid/volumes/kubernetes.io~azure-file/vol1")
|
||||||
|
path := builder.GetPath()
|
||||||
|
if path != volPath {
|
||||||
|
t.Errorf("Got unexpected path: %s", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := builder.SetUp(nil); err != nil {
|
||||||
|
t.Errorf("Expected success, got: %v", err)
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(path); err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
t.Errorf("SetUp() failed, volume path not created: %s", path)
|
||||||
|
} else {
|
||||||
|
t.Errorf("SetUp() failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(path); err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
t.Errorf("SetUp() failed, volume path not created: %s", path)
|
||||||
|
} else {
|
||||||
|
t.Errorf("SetUp() failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cleaner, err := plug.(*azureFilePlugin).newCleanerInternal("vol1", types.UID("poduid"), &mount.FakeMounter{})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to make a new Cleaner: %v", err)
|
||||||
|
}
|
||||||
|
if cleaner == nil {
|
||||||
|
t.Errorf("Got a nil Cleaner")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cleaner.TearDown(); err != nil {
|
||||||
|
t.Errorf("Expected success, got: %v", err)
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(path); err == nil {
|
||||||
|
t.Errorf("TearDown() failed, volume path still exists: %s", path)
|
||||||
|
} else if !os.IsNotExist(err) {
|
||||||
|
t.Errorf("SetUp() failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPersistentClaimReadOnlyFlag(t *testing.T) {
|
||||||
|
pv := &api.PersistentVolume{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "pvA",
|
||||||
|
},
|
||||||
|
Spec: api.PersistentVolumeSpec{
|
||||||
|
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||||
|
AzureFile: &api.AzureFileVolumeSource{},
|
||||||
|
},
|
||||||
|
ClaimRef: &api.ObjectReference{
|
||||||
|
Name: "claimA",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
claim := &api.PersistentVolumeClaim{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "claimA",
|
||||||
|
Namespace: "nsA",
|
||||||
|
},
|
||||||
|
Spec: api.PersistentVolumeClaimSpec{
|
||||||
|
VolumeName: "pvA",
|
||||||
|
},
|
||||||
|
Status: api.PersistentVolumeClaimStatus{
|
||||||
|
Phase: api.ClaimBound,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
client := fake.NewSimpleClientset(pv, claim)
|
||||||
|
|
||||||
|
plugMgr := volume.VolumePluginMgr{}
|
||||||
|
plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", client, nil))
|
||||||
|
plug, _ := plugMgr.FindPluginByName(azureFilePluginName)
|
||||||
|
|
||||||
|
// readOnly bool is supplied by persistent-claim volume source when its builder creates other volumes
|
||||||
|
spec := volume.NewSpecFromPersistentVolume(pv, true)
|
||||||
|
pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}}
|
||||||
|
builder, _ := plug.NewBuilder(spec, pod, volume.VolumeOptions{})
|
||||||
|
|
||||||
|
if !builder.GetAttributes().ReadOnly {
|
||||||
|
t.Errorf("Expected true for builder.IsReadOnly")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type fakeAzureSvc struct{}
|
||||||
|
|
||||||
|
func (s *fakeAzureSvc) GetAzureCredentials(host volume.VolumeHost, nameSpace, secretName, shareName string) (string, string, error) {
|
||||||
|
return "name", "key", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuilderAndCleanerTypeAssert(t *testing.T) {
|
||||||
|
tmpDir, err := ioutil.TempDir(os.TempDir(), "azurefileTest")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't make a temp dir: %v", err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
plugMgr := volume.VolumePluginMgr{}
|
||||||
|
plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost(tmpDir, nil, nil))
|
||||||
|
|
||||||
|
plug, err := plugMgr.FindPluginByName("kubernetes.io/azure-file")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Can't find the plugin by name")
|
||||||
|
}
|
||||||
|
spec := &api.Volume{
|
||||||
|
Name: "vol1",
|
||||||
|
VolumeSource: api.VolumeSource{
|
||||||
|
AzureFile: &api.AzureFileVolumeSource{
|
||||||
|
SecretName: "secret",
|
||||||
|
ShareName: "share",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
fake := &mount.FakeMounter{}
|
||||||
|
pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}}
|
||||||
|
builder, err := plug.(*azureFilePlugin).newBuilderInternal(volume.NewSpecFromVolume(spec), pod, &fakeAzureSvc{}, fake)
|
||||||
|
if _, ok := builder.(volume.Cleaner); ok {
|
||||||
|
t.Errorf("Volume Builder can be type-assert to Cleaner")
|
||||||
|
}
|
||||||
|
|
||||||
|
cleaner, err := plug.(*azureFilePlugin).newCleanerInternal("vol1", types.UID("poduid"), &mount.FakeMounter{})
|
||||||
|
if _, ok := cleaner.(volume.Builder); ok {
|
||||||
|
t.Errorf("Volume Cleaner can be type-assert to Builder")
|
||||||
|
}
|
||||||
|
}
|
55
pkg/volume/azure_file/azure_util.go
Normal file
55
pkg/volume/azure_file/azure_util.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
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 azure_file
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Abstract interface to azure file operations.
|
||||||
|
type azureUtil interface {
|
||||||
|
GetAzureCredentials(host volume.VolumeHost, nameSpace, secretName, shareName string) (string, string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type azureSvc struct{}
|
||||||
|
|
||||||
|
func (s *azureSvc) GetAzureCredentials(host volume.VolumeHost, nameSpace, secretName, shareName string) (string, string, error) {
|
||||||
|
var accountKey, accountName string
|
||||||
|
kubeClient := host.GetKubeClient()
|
||||||
|
if kubeClient == nil {
|
||||||
|
return "", "", fmt.Errorf("Cannot get kube client")
|
||||||
|
}
|
||||||
|
|
||||||
|
keys, err := kubeClient.Core().Secrets(nameSpace).Get(secretName)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", fmt.Errorf("Couldn't get secret %v/%v", nameSpace, secretName)
|
||||||
|
}
|
||||||
|
for name, data := range keys.Data {
|
||||||
|
if name == "azurestorageaccountname" {
|
||||||
|
accountName = string(data)
|
||||||
|
}
|
||||||
|
if name == "azurestorageaccountkey" {
|
||||||
|
accountKey = string(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if accountName == "" || accountKey == "" {
|
||||||
|
return "", "", fmt.Errorf("Invalid %v/%v, couldn't extract azurestorageaccountname or azurestorageaccountkey", nameSpace, secretName)
|
||||||
|
}
|
||||||
|
return accountName, accountKey, nil
|
||||||
|
}
|
19
pkg/volume/azure_file/doc.go
Normal file
19
pkg/volume/azure_file/doc.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||||
|
|
||||||
|
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 azure_file contains the internal representation of
|
||||||
|
// Azure File Service Volume
|
||||||
|
package azure_file
|
Loading…
Reference in New Issue
Block a user