mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 17:30:00 +00:00
Merge pull request #54302 from sbezverk/refactor_rbd_volume
Automatic merge from submit-queue (batch tested with PRs 54229, 54380, 54302, 54454). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Refactor RBD volume Refactor RBD Volume Persistent Volume Spec so RBD PV's SecretRef allows referencing a secret from a persistent volume in any namespace. This allows locating credentials for persistent volumes in namespaces other than the one containing the PVC. Closes #54432 ```release-note RBD Persistent Volume Sources can now reference User's Secret in namespaces other than the namespace of the bound Persistent Volume Claim ```
This commit is contained in:
commit
16cdda003c
@ -68781,7 +68781,7 @@
|
|||||||
},
|
},
|
||||||
"rbd": {
|
"rbd": {
|
||||||
"description": "RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md",
|
"description": "RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md",
|
||||||
"$ref": "#/definitions/io.k8s.api.core.v1.RBDVolumeSource"
|
"$ref": "#/definitions/io.k8s.api.core.v1.RBDPersistentVolumeSource"
|
||||||
},
|
},
|
||||||
"scaleIO": {
|
"scaleIO": {
|
||||||
"description": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.",
|
"description": "ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes.",
|
||||||
@ -69424,6 +69424,50 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"io.k8s.api.core.v1.RBDPersistentVolumeSource": {
|
||||||
|
"description": "Represents a Rados Block Device mount that lasts the lifetime of a pod. RBD volumes support ownership management and SELinux relabeling.",
|
||||||
|
"required": [
|
||||||
|
"monitors",
|
||||||
|
"image"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"fsType": {
|
||||||
|
"description": "Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"description": "The rados image name. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"keyring": {
|
||||||
|
"description": "Keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"monitors": {
|
||||||
|
"description": "A collection of Ceph monitors. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pool": {
|
||||||
|
"description": "The rados pool name. Default is rbd. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"readOnly": {
|
||||||
|
"description": "ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"secretRef": {
|
||||||
|
"description": "SecretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it",
|
||||||
|
"$ref": "#/definitions/io.k8s.api.core.v1.SecretReference"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"description": "The rados user name. Default is admin. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"io.k8s.api.core.v1.RBDVolumeSource": {
|
"io.k8s.api.core.v1.RBDVolumeSource": {
|
||||||
"description": "Represents a Rados Block Device mount that lasts the lifetime of a pod. RBD volumes support ownership management and SELinux relabeling.",
|
"description": "Represents a Rados Block Device mount that lasts the lifetime of a pod. RBD volumes support ownership management and SELinux relabeling.",
|
||||||
"required": [
|
"required": [
|
||||||
|
@ -20529,7 +20529,7 @@
|
|||||||
"description": "NFS represents an NFS mount on the host. Provisioned by an admin. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs"
|
"description": "NFS represents an NFS mount on the host. Provisioned by an admin. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs"
|
||||||
},
|
},
|
||||||
"rbd": {
|
"rbd": {
|
||||||
"$ref": "v1.RBDVolumeSource",
|
"$ref": "v1.RBDPersistentVolumeSource",
|
||||||
"description": "RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md"
|
"description": "RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md"
|
||||||
},
|
},
|
||||||
"iscsi": {
|
"iscsi": {
|
||||||
@ -20737,8 +20737,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"v1.RBDVolumeSource": {
|
"v1.RBDPersistentVolumeSource": {
|
||||||
"id": "v1.RBDVolumeSource",
|
"id": "v1.RBDPersistentVolumeSource",
|
||||||
"description": "Represents a Rados Block Device mount that lasts the lifetime of a pod. RBD volumes support ownership management and SELinux relabeling.",
|
"description": "Represents a Rados Block Device mount that lasts the lifetime of a pod. RBD volumes support ownership management and SELinux relabeling.",
|
||||||
"required": [
|
"required": [
|
||||||
"monitors",
|
"monitors",
|
||||||
@ -20773,7 +20773,7 @@
|
|||||||
"description": "Keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it"
|
"description": "Keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it"
|
||||||
},
|
},
|
||||||
"secretRef": {
|
"secretRef": {
|
||||||
"$ref": "v1.LocalObjectReference",
|
"$ref": "v1.SecretReference",
|
||||||
"description": "SecretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it"
|
"description": "SecretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it"
|
||||||
},
|
},
|
||||||
"readOnly": {
|
"readOnly": {
|
||||||
@ -20782,13 +20782,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"v1.LocalObjectReference": {
|
"v1.SecretReference": {
|
||||||
"id": "v1.LocalObjectReference",
|
"id": "v1.SecretReference",
|
||||||
"description": "LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace.",
|
"description": "SecretReference represents a Secret Reference. It has enough information to retrieve secret in any namespace",
|
||||||
"properties": {
|
"properties": {
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names"
|
"description": "Name is unique within a namespace to reference a secret resource."
|
||||||
|
},
|
||||||
|
"namespace": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Namespace defines the space within which the secret name must be unique."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -20851,6 +20855,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"v1.LocalObjectReference": {
|
||||||
|
"id": "v1.LocalObjectReference",
|
||||||
|
"description": "LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace.",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"v1.CinderVolumeSource": {
|
"v1.CinderVolumeSource": {
|
||||||
"id": "v1.CinderVolumeSource",
|
"id": "v1.CinderVolumeSource",
|
||||||
"description": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.",
|
"description": "Represents a cinder volume resource in Openstack. A Cinder volume must exist before mounting to a container. The volume must also be in the same region as the kubelet. Cinder volumes support ownership management and SELinux relabeling.",
|
||||||
@ -20908,20 +20922,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"v1.SecretReference": {
|
|
||||||
"id": "v1.SecretReference",
|
|
||||||
"description": "SecretReference represents a Secret Reference. It has enough information to retrieve secret in any namespace",
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Name is unique within a namespace to reference a secret resource."
|
|
||||||
},
|
|
||||||
"namespace": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Namespace defines the space within which the secret name must be unique."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"v1.FCVolumeSource": {
|
"v1.FCVolumeSource": {
|
||||||
"id": "v1.FCVolumeSource",
|
"id": "v1.FCVolumeSource",
|
||||||
"description": "Represents a Fibre Channel volume. Fibre Channel volumes can only be mounted as read/write once. Fibre Channel volumes support ownership management and SELinux relabeling.",
|
"description": "Represents a Fibre Channel volume. Fibre Channel volumes can only be mounted as read/write once. Fibre Channel volumes support ownership management and SELinux relabeling.",
|
||||||
@ -21674,6 +21674,51 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"v1.RBDVolumeSource": {
|
||||||
|
"id": "v1.RBDVolumeSource",
|
||||||
|
"description": "Represents a Rados Block Device mount that lasts the lifetime of a pod. RBD volumes support ownership management and SELinux relabeling.",
|
||||||
|
"required": [
|
||||||
|
"monitors",
|
||||||
|
"image"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"monitors": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "A collection of Ceph monitors. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it"
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The rados image name. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it"
|
||||||
|
},
|
||||||
|
"fsType": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd"
|
||||||
|
},
|
||||||
|
"pool": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The rados pool name. Default is rbd. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The rados user name. Default is admin. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it"
|
||||||
|
},
|
||||||
|
"keyring": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it"
|
||||||
|
},
|
||||||
|
"secretRef": {
|
||||||
|
"$ref": "v1.LocalObjectReference",
|
||||||
|
"description": "SecretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it"
|
||||||
|
},
|
||||||
|
"readOnly": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"v1.CephFSVolumeSource": {
|
"v1.CephFSVolumeSource": {
|
||||||
"id": "v1.CephFSVolumeSource",
|
"id": "v1.CephFSVolumeSource",
|
||||||
"description": "Represents a Ceph Filesystem mount that lasts the lifetime of a pod Cephfs volumes do not support ownership management or SELinux relabeling.",
|
"description": "Represents a Ceph Filesystem mount that lasts the lifetime of a pod Cephfs volumes do not support ownership management or SELinux relabeling.",
|
||||||
|
@ -7636,7 +7636,7 @@ Examples:<br>
|
|||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">rbd</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">rbd</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">RBD represents a Rados Block Device mount on the host that shares a pod’s lifetime. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md">https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md</a></p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">RBD represents a Rados Block Device mount on the host that shares a pod’s lifetime. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md">https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md</a></p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_rbdvolumesource">v1.RBDVolumeSource</a></p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_rbdpersistentvolumesource">v1.RBDPersistentVolumeSource</a></p></td>
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -8525,6 +8525,89 @@ Examples:<br>
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="sect2">
|
||||||
|
<h3 id="_v1_rbdpersistentvolumesource">v1.RBDPersistentVolumeSource</h3>
|
||||||
|
<div class="paragraph">
|
||||||
|
<p>Represents a Rados Block Device mount that lasts the lifetime of a pod. RBD volumes support ownership management and SELinux relabeling.</p>
|
||||||
|
</div>
|
||||||
|
<table class="tableblock frame-all grid-all" style="width:100%; ">
|
||||||
|
<colgroup>
|
||||||
|
<col style="width:20%;">
|
||||||
|
<col style="width:20%;">
|
||||||
|
<col style="width:20%;">
|
||||||
|
<col style="width:20%;">
|
||||||
|
<col style="width:20%;">
|
||||||
|
</colgroup>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="tableblock halign-left valign-top">Name</th>
|
||||||
|
<th class="tableblock halign-left valign-top">Description</th>
|
||||||
|
<th class="tableblock halign-left valign-top">Required</th>
|
||||||
|
<th class="tableblock halign-left valign-top">Schema</th>
|
||||||
|
<th class="tableblock halign-left valign-top">Default</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">monitors</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">A collection of Ceph monitors. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it">https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it</a></p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string array</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">image</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">The rados image name. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it">https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it</a></p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">fsType</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: <a href="https://kubernetes.io/docs/concepts/storage/volumes#rbd">https://kubernetes.io/docs/concepts/storage/volumes#rbd</a></p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">pool</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">The rados pool name. Default is rbd. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it">https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it</a></p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">user</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">The rados user name. Default is admin. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it">https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it</a></p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">keyring</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it">https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it</a></p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">secretRef</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">SecretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it">https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it</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_secretreference">v1.SecretReference</a></p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">readOnly</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it">https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it</a></p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="sect2">
|
<div class="sect2">
|
||||||
<h3 id="_v1_cindervolumesource">v1.CinderVolumeSource</h3>
|
<h3 id="_v1_cindervolumesource">v1.CinderVolumeSource</h3>
|
||||||
|
@ -355,6 +355,20 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
|
|||||||
r.Keyring = "/etc/ceph/keyring"
|
r.Keyring = "/etc/ceph/keyring"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
func(r *api.RBDPersistentVolumeSource, c fuzz.Continue) {
|
||||||
|
r.RBDPool = c.RandString()
|
||||||
|
if r.RBDPool == "" {
|
||||||
|
r.RBDPool = "rbd"
|
||||||
|
}
|
||||||
|
r.RadosUser = c.RandString()
|
||||||
|
if r.RadosUser == "" {
|
||||||
|
r.RadosUser = "admin"
|
||||||
|
}
|
||||||
|
r.Keyring = c.RandString()
|
||||||
|
if r.Keyring == "" {
|
||||||
|
r.Keyring = "/etc/ceph/keyring"
|
||||||
|
}
|
||||||
|
},
|
||||||
func(obj *api.HostPathVolumeSource, c fuzz.Continue) {
|
func(obj *api.HostPathVolumeSource, c fuzz.Continue) {
|
||||||
c.FuzzNoCustom(obj)
|
c.FuzzNoCustom(obj)
|
||||||
types := []api.HostPathType{api.HostPathUnset, api.HostPathDirectoryOrCreate, api.HostPathDirectory,
|
types := []api.HostPathType{api.HostPathUnset, api.HostPathDirectoryOrCreate, api.HostPathDirectory,
|
||||||
|
@ -64,9 +64,17 @@ func VisitPVSecretNames(pv *api.PersistentVolume, visitor Visitor) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case source.RBD != nil:
|
case source.RBD != nil:
|
||||||
if source.RBD.SecretRef != nil && !visitor(getClaimRefNamespace(pv), source.RBD.SecretRef.Name) {
|
if source.RBD.SecretRef != nil {
|
||||||
|
// previously persisted PV objects use claimRef namespace
|
||||||
|
ns := getClaimRefNamespace(pv)
|
||||||
|
if len(source.RBD.SecretRef.Namespace) > 0 {
|
||||||
|
// use the secret namespace if namespace is set
|
||||||
|
ns = source.RBD.SecretRef.Namespace
|
||||||
|
}
|
||||||
|
if !visitor(ns, source.RBD.SecretRef.Name) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
case source.ScaleIO != nil:
|
case source.ScaleIO != nil:
|
||||||
if source.ScaleIO.SecretRef != nil && !visitor(getClaimRefNamespace(pv), source.ScaleIO.SecretRef.Name) {
|
if source.ScaleIO.SecretRef != nil && !visitor(getClaimRefNamespace(pv), source.ScaleIO.SecretRef.Name) {
|
||||||
return false
|
return false
|
||||||
|
@ -65,9 +65,16 @@ func TestPVSecrets(t *testing.T) {
|
|||||||
{Spec: api.PersistentVolumeSpec{
|
{Spec: api.PersistentVolumeSpec{
|
||||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||||
RBD: &api.RBDVolumeSource{
|
RBD: &api.RBDPersistentVolumeSource{
|
||||||
SecretRef: &api.LocalObjectReference{
|
SecretRef: &api.SecretReference{
|
||||||
Name: "Spec.PersistentVolumeSource.RBD.SecretRef"}}}}},
|
Name: "Spec.PersistentVolumeSource.RBD.SecretRef"}}}}},
|
||||||
|
{Spec: api.PersistentVolumeSpec{
|
||||||
|
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||||
|
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||||
|
RBD: &api.RBDPersistentVolumeSource{
|
||||||
|
SecretRef: &api.SecretReference{
|
||||||
|
Name: "Spec.PersistentVolumeSource.RBD.SecretRef",
|
||||||
|
Namespace: "rbdns"}}}}},
|
||||||
{Spec: api.PersistentVolumeSpec{
|
{Spec: api.PersistentVolumeSpec{
|
||||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||||
@ -141,6 +148,7 @@ func TestPVSecrets(t *testing.T) {
|
|||||||
"cephfs/Spec.PersistentVolumeSource.CephFS.SecretRef",
|
"cephfs/Spec.PersistentVolumeSource.CephFS.SecretRef",
|
||||||
"claimrefns/Spec.PersistentVolumeSource.FlexVolume.SecretRef",
|
"claimrefns/Spec.PersistentVolumeSource.FlexVolume.SecretRef",
|
||||||
"claimrefns/Spec.PersistentVolumeSource.RBD.SecretRef",
|
"claimrefns/Spec.PersistentVolumeSource.RBD.SecretRef",
|
||||||
|
"rbdns/Spec.PersistentVolumeSource.RBD.SecretRef",
|
||||||
"claimrefns/Spec.PersistentVolumeSource.ScaleIO.SecretRef",
|
"claimrefns/Spec.PersistentVolumeSource.ScaleIO.SecretRef",
|
||||||
"claimrefns/Spec.PersistentVolumeSource.ISCSI.SecretRef",
|
"claimrefns/Spec.PersistentVolumeSource.ISCSI.SecretRef",
|
||||||
"storageosns/Spec.PersistentVolumeSource.StorageOS.SecretRef",
|
"storageosns/Spec.PersistentVolumeSource.StorageOS.SecretRef",
|
||||||
|
@ -343,7 +343,7 @@ type PersistentVolumeSource struct {
|
|||||||
NFS *NFSVolumeSource
|
NFS *NFSVolumeSource
|
||||||
// RBD represents a Rados Block Device mount on the host that shares a pod's lifetime
|
// RBD represents a Rados Block Device mount on the host that shares a pod's lifetime
|
||||||
// +optional
|
// +optional
|
||||||
RBD *RBDVolumeSource
|
RBD *RBDPersistentVolumeSource
|
||||||
// Quobyte represents a Quobyte mount on the host that shares a pod's lifetime
|
// Quobyte represents a Quobyte mount on the host that shares a pod's lifetime
|
||||||
// +optional
|
// +optional
|
||||||
Quobyte *QuobyteVolumeSource
|
Quobyte *QuobyteVolumeSource
|
||||||
@ -1006,6 +1006,37 @@ type RBDVolumeSource struct {
|
|||||||
ReadOnly bool
|
ReadOnly bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Represents a Rados Block Device mount that lasts the lifetime of a pod.
|
||||||
|
// RBD volumes support ownership management and SELinux relabeling.
|
||||||
|
type RBDPersistentVolumeSource struct {
|
||||||
|
// Required: CephMonitors is a collection of Ceph monitors
|
||||||
|
CephMonitors []string
|
||||||
|
// Required: RBDImage is the rados image name
|
||||||
|
RBDImage string
|
||||||
|
// Filesystem type to mount.
|
||||||
|
// Must be a filesystem type supported by the host operating system.
|
||||||
|
// Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified.
|
||||||
|
// TODO: how do we prevent errors in the filesystem from compromising the machine
|
||||||
|
// +optional
|
||||||
|
FSType string
|
||||||
|
// Optional: RadosPool is the rados pool name,default is rbd
|
||||||
|
// +optional
|
||||||
|
RBDPool string
|
||||||
|
// Optional: RBDUser is the rados user name, default is admin
|
||||||
|
// +optional
|
||||||
|
RadosUser string
|
||||||
|
// Optional: Keyring is the path to key ring for RBDUser, default is /etc/ceph/keyring
|
||||||
|
// +optional
|
||||||
|
Keyring string
|
||||||
|
// Optional: SecretRef is reference to the authentication secret for User, default is empty.
|
||||||
|
// +optional
|
||||||
|
SecretRef *SecretReference
|
||||||
|
// Optional: Defaults to false (read/write). ReadOnly here will force
|
||||||
|
// the ReadOnly setting in VolumeMounts.
|
||||||
|
// +optional
|
||||||
|
ReadOnly bool
|
||||||
|
}
|
||||||
|
|
||||||
// Represents a cinder volume resource in Openstack. A Cinder volume
|
// Represents a cinder volume resource in Openstack. A Cinder volume
|
||||||
// must exist before mounting to a container. The volume must also be
|
// must exist before mounting to a container. The volume must also be
|
||||||
// in the same region as the kubelet. Cinder volumes support ownership
|
// in the same region as the kubelet. Cinder volumes support ownership
|
||||||
|
@ -368,6 +368,18 @@ func SetDefaults_RBDVolumeSource(obj *v1.RBDVolumeSource) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetDefaults_RBDPersistentVolumeSource(obj *v1.RBDPersistentVolumeSource) {
|
||||||
|
if obj.RBDPool == "" {
|
||||||
|
obj.RBDPool = "rbd"
|
||||||
|
}
|
||||||
|
if obj.RadosUser == "" {
|
||||||
|
obj.RadosUser = "admin"
|
||||||
|
}
|
||||||
|
if obj.Keyring == "" {
|
||||||
|
obj.Keyring = "/etc/ceph/keyring"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func SetDefaults_ScaleIOVolumeSource(obj *v1.ScaleIOVolumeSource) {
|
func SetDefaults_ScaleIOVolumeSource(obj *v1.ScaleIOVolumeSource) {
|
||||||
if obj.ProtectionDomain == "" {
|
if obj.ProtectionDomain == "" {
|
||||||
obj.ProtectionDomain = "default"
|
obj.ProtectionDomain = "default"
|
||||||
|
@ -305,6 +305,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
|
|||||||
Convert_api_ProjectedVolumeSource_To_v1_ProjectedVolumeSource,
|
Convert_api_ProjectedVolumeSource_To_v1_ProjectedVolumeSource,
|
||||||
Convert_v1_QuobyteVolumeSource_To_api_QuobyteVolumeSource,
|
Convert_v1_QuobyteVolumeSource_To_api_QuobyteVolumeSource,
|
||||||
Convert_api_QuobyteVolumeSource_To_v1_QuobyteVolumeSource,
|
Convert_api_QuobyteVolumeSource_To_v1_QuobyteVolumeSource,
|
||||||
|
Convert_v1_RBDPersistentVolumeSource_To_api_RBDPersistentVolumeSource,
|
||||||
|
Convert_api_RBDPersistentVolumeSource_To_v1_RBDPersistentVolumeSource,
|
||||||
Convert_v1_RBDVolumeSource_To_api_RBDVolumeSource,
|
Convert_v1_RBDVolumeSource_To_api_RBDVolumeSource,
|
||||||
Convert_api_RBDVolumeSource_To_v1_RBDVolumeSource,
|
Convert_api_RBDVolumeSource_To_v1_RBDVolumeSource,
|
||||||
Convert_v1_RangeAllocation_To_api_RangeAllocation,
|
Convert_v1_RangeAllocation_To_api_RangeAllocation,
|
||||||
@ -3124,7 +3126,7 @@ func autoConvert_v1_PersistentVolumeSource_To_api_PersistentVolumeSource(in *v1.
|
|||||||
out.HostPath = (*api.HostPathVolumeSource)(unsafe.Pointer(in.HostPath))
|
out.HostPath = (*api.HostPathVolumeSource)(unsafe.Pointer(in.HostPath))
|
||||||
out.Glusterfs = (*api.GlusterfsVolumeSource)(unsafe.Pointer(in.Glusterfs))
|
out.Glusterfs = (*api.GlusterfsVolumeSource)(unsafe.Pointer(in.Glusterfs))
|
||||||
out.NFS = (*api.NFSVolumeSource)(unsafe.Pointer(in.NFS))
|
out.NFS = (*api.NFSVolumeSource)(unsafe.Pointer(in.NFS))
|
||||||
out.RBD = (*api.RBDVolumeSource)(unsafe.Pointer(in.RBD))
|
out.RBD = (*api.RBDPersistentVolumeSource)(unsafe.Pointer(in.RBD))
|
||||||
out.ISCSI = (*api.ISCSIVolumeSource)(unsafe.Pointer(in.ISCSI))
|
out.ISCSI = (*api.ISCSIVolumeSource)(unsafe.Pointer(in.ISCSI))
|
||||||
out.Cinder = (*api.CinderVolumeSource)(unsafe.Pointer(in.Cinder))
|
out.Cinder = (*api.CinderVolumeSource)(unsafe.Pointer(in.Cinder))
|
||||||
out.CephFS = (*api.CephFSPersistentVolumeSource)(unsafe.Pointer(in.CephFS))
|
out.CephFS = (*api.CephFSPersistentVolumeSource)(unsafe.Pointer(in.CephFS))
|
||||||
@ -3154,7 +3156,7 @@ func autoConvert_api_PersistentVolumeSource_To_v1_PersistentVolumeSource(in *api
|
|||||||
out.HostPath = (*v1.HostPathVolumeSource)(unsafe.Pointer(in.HostPath))
|
out.HostPath = (*v1.HostPathVolumeSource)(unsafe.Pointer(in.HostPath))
|
||||||
out.Glusterfs = (*v1.GlusterfsVolumeSource)(unsafe.Pointer(in.Glusterfs))
|
out.Glusterfs = (*v1.GlusterfsVolumeSource)(unsafe.Pointer(in.Glusterfs))
|
||||||
out.NFS = (*v1.NFSVolumeSource)(unsafe.Pointer(in.NFS))
|
out.NFS = (*v1.NFSVolumeSource)(unsafe.Pointer(in.NFS))
|
||||||
out.RBD = (*v1.RBDVolumeSource)(unsafe.Pointer(in.RBD))
|
out.RBD = (*v1.RBDPersistentVolumeSource)(unsafe.Pointer(in.RBD))
|
||||||
out.Quobyte = (*v1.QuobyteVolumeSource)(unsafe.Pointer(in.Quobyte))
|
out.Quobyte = (*v1.QuobyteVolumeSource)(unsafe.Pointer(in.Quobyte))
|
||||||
out.ISCSI = (*v1.ISCSIVolumeSource)(unsafe.Pointer(in.ISCSI))
|
out.ISCSI = (*v1.ISCSIVolumeSource)(unsafe.Pointer(in.ISCSI))
|
||||||
out.FlexVolume = (*v1.FlexVolumeSource)(unsafe.Pointer(in.FlexVolume))
|
out.FlexVolume = (*v1.FlexVolumeSource)(unsafe.Pointer(in.FlexVolume))
|
||||||
@ -4062,6 +4064,40 @@ func Convert_api_QuobyteVolumeSource_To_v1_QuobyteVolumeSource(in *api.QuobyteVo
|
|||||||
return autoConvert_api_QuobyteVolumeSource_To_v1_QuobyteVolumeSource(in, out, s)
|
return autoConvert_api_QuobyteVolumeSource_To_v1_QuobyteVolumeSource(in, out, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func autoConvert_v1_RBDPersistentVolumeSource_To_api_RBDPersistentVolumeSource(in *v1.RBDPersistentVolumeSource, out *api.RBDPersistentVolumeSource, s conversion.Scope) error {
|
||||||
|
out.CephMonitors = *(*[]string)(unsafe.Pointer(&in.CephMonitors))
|
||||||
|
out.RBDImage = in.RBDImage
|
||||||
|
out.FSType = in.FSType
|
||||||
|
out.RBDPool = in.RBDPool
|
||||||
|
out.RadosUser = in.RadosUser
|
||||||
|
out.Keyring = in.Keyring
|
||||||
|
out.SecretRef = (*api.SecretReference)(unsafe.Pointer(in.SecretRef))
|
||||||
|
out.ReadOnly = in.ReadOnly
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_v1_RBDPersistentVolumeSource_To_api_RBDPersistentVolumeSource is an autogenerated conversion function.
|
||||||
|
func Convert_v1_RBDPersistentVolumeSource_To_api_RBDPersistentVolumeSource(in *v1.RBDPersistentVolumeSource, out *api.RBDPersistentVolumeSource, s conversion.Scope) error {
|
||||||
|
return autoConvert_v1_RBDPersistentVolumeSource_To_api_RBDPersistentVolumeSource(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvert_api_RBDPersistentVolumeSource_To_v1_RBDPersistentVolumeSource(in *api.RBDPersistentVolumeSource, out *v1.RBDPersistentVolumeSource, s conversion.Scope) error {
|
||||||
|
out.CephMonitors = *(*[]string)(unsafe.Pointer(&in.CephMonitors))
|
||||||
|
out.RBDImage = in.RBDImage
|
||||||
|
out.FSType = in.FSType
|
||||||
|
out.RBDPool = in.RBDPool
|
||||||
|
out.RadosUser = in.RadosUser
|
||||||
|
out.Keyring = in.Keyring
|
||||||
|
out.SecretRef = (*v1.SecretReference)(unsafe.Pointer(in.SecretRef))
|
||||||
|
out.ReadOnly = in.ReadOnly
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_api_RBDPersistentVolumeSource_To_v1_RBDPersistentVolumeSource is an autogenerated conversion function.
|
||||||
|
func Convert_api_RBDPersistentVolumeSource_To_v1_RBDPersistentVolumeSource(in *api.RBDPersistentVolumeSource, out *v1.RBDPersistentVolumeSource, s conversion.Scope) error {
|
||||||
|
return autoConvert_api_RBDPersistentVolumeSource_To_v1_RBDPersistentVolumeSource(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
func autoConvert_v1_RBDVolumeSource_To_api_RBDVolumeSource(in *v1.RBDVolumeSource, out *api.RBDVolumeSource, s conversion.Scope) error {
|
func autoConvert_v1_RBDVolumeSource_To_api_RBDVolumeSource(in *v1.RBDVolumeSource, out *api.RBDVolumeSource, s conversion.Scope) error {
|
||||||
out.CephMonitors = *(*[]string)(unsafe.Pointer(&in.CephMonitors))
|
out.CephMonitors = *(*[]string)(unsafe.Pointer(&in.CephMonitors))
|
||||||
out.RBDImage = in.RBDImage
|
out.RBDImage = in.RBDImage
|
||||||
|
@ -137,7 +137,7 @@ func SetObjectDefaults_PersistentVolume(in *v1.PersistentVolume) {
|
|||||||
SetDefaults_HostPathVolumeSource(in.Spec.PersistentVolumeSource.HostPath)
|
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_RBDPersistentVolumeSource(in.Spec.PersistentVolumeSource.RBD)
|
||||||
}
|
}
|
||||||
if in.Spec.PersistentVolumeSource.ISCSI != nil {
|
if in.Spec.PersistentVolumeSource.ISCSI != nil {
|
||||||
SetDefaults_ISCSIVolumeSource(in.Spec.PersistentVolumeSource.ISCSI)
|
SetDefaults_ISCSIVolumeSource(in.Spec.PersistentVolumeSource.ISCSI)
|
||||||
|
@ -1088,6 +1088,17 @@ func validateRBDVolumeSource(rbd *api.RBDVolumeSource, fldPath *field.Path) fiel
|
|||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateRBDPersistentVolumeSource(rbd *api.RBDPersistentVolumeSource, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
if len(rbd.CephMonitors) == 0 {
|
||||||
|
allErrs = append(allErrs, field.Required(fldPath.Child("monitors"), ""))
|
||||||
|
}
|
||||||
|
if len(rbd.RBDImage) == 0 {
|
||||||
|
allErrs = append(allErrs, field.Required(fldPath.Child("image"), ""))
|
||||||
|
}
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
func validateCinderVolumeSource(cd *api.CinderVolumeSource, fldPath *field.Path) field.ErrorList {
|
func validateCinderVolumeSource(cd *api.CinderVolumeSource, fldPath *field.Path) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
if len(cd.VolumeID) == 0 {
|
if len(cd.VolumeID) == 0 {
|
||||||
@ -1380,7 +1391,7 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) field.ErrorList {
|
|||||||
allErrs = append(allErrs, field.Forbidden(specPath.Child("rbd"), "may not specify more than 1 volume type"))
|
allErrs = append(allErrs, field.Forbidden(specPath.Child("rbd"), "may not specify more than 1 volume type"))
|
||||||
} else {
|
} else {
|
||||||
numVolumes++
|
numVolumes++
|
||||||
allErrs = append(allErrs, validateRBDVolumeSource(pv.Spec.RBD, specPath.Child("rbd"))...)
|
allErrs = append(allErrs, validateRBDPersistentVolumeSource(pv.Spec.RBD, specPath.Child("rbd"))...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if pv.Spec.Quobyte != nil {
|
if pv.Spec.Quobyte != nil {
|
||||||
|
@ -571,6 +571,10 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
|
|||||||
in.(*QuobyteVolumeSource).DeepCopyInto(out.(*QuobyteVolumeSource))
|
in.(*QuobyteVolumeSource).DeepCopyInto(out.(*QuobyteVolumeSource))
|
||||||
return nil
|
return nil
|
||||||
}, InType: reflect.TypeOf(&QuobyteVolumeSource{})},
|
}, InType: reflect.TypeOf(&QuobyteVolumeSource{})},
|
||||||
|
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||||
|
in.(*RBDPersistentVolumeSource).DeepCopyInto(out.(*RBDPersistentVolumeSource))
|
||||||
|
return nil
|
||||||
|
}, InType: reflect.TypeOf(&RBDPersistentVolumeSource{})},
|
||||||
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
|
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||||
in.(*RBDVolumeSource).DeepCopyInto(out.(*RBDVolumeSource))
|
in.(*RBDVolumeSource).DeepCopyInto(out.(*RBDVolumeSource))
|
||||||
return nil
|
return nil
|
||||||
@ -3747,7 +3751,7 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) {
|
|||||||
if *in == nil {
|
if *in == nil {
|
||||||
*out = nil
|
*out = nil
|
||||||
} else {
|
} else {
|
||||||
*out = new(RBDVolumeSource)
|
*out = new(RBDPersistentVolumeSource)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4815,6 +4819,36 @@ func (in *QuobyteVolumeSource) DeepCopy() *QuobyteVolumeSource {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *RBDPersistentVolumeSource) DeepCopyInto(out *RBDPersistentVolumeSource) {
|
||||||
|
*out = *in
|
||||||
|
if in.CephMonitors != nil {
|
||||||
|
in, out := &in.CephMonitors, &out.CephMonitors
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
if in.SecretRef != nil {
|
||||||
|
in, out := &in.SecretRef, &out.SecretRef
|
||||||
|
if *in == nil {
|
||||||
|
*out = nil
|
||||||
|
} else {
|
||||||
|
*out = new(SecretReference)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RBDPersistentVolumeSource.
|
||||||
|
func (in *RBDPersistentVolumeSource) DeepCopy() *RBDPersistentVolumeSource {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(RBDPersistentVolumeSource)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *RBDVolumeSource) DeepCopyInto(out *RBDVolumeSource) {
|
func (in *RBDVolumeSource) DeepCopyInto(out *RBDVolumeSource) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
@ -898,6 +898,19 @@ func printRBDVolumeSource(rbd *api.RBDVolumeSource, w PrefixWriter) {
|
|||||||
rbd.CephMonitors, rbd.RBDImage, rbd.FSType, rbd.RBDPool, rbd.RadosUser, rbd.Keyring, rbd.SecretRef, rbd.ReadOnly)
|
rbd.CephMonitors, rbd.RBDImage, rbd.FSType, rbd.RBDPool, rbd.RadosUser, rbd.Keyring, rbd.SecretRef, rbd.ReadOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printRBDPersistentVolumeSource(rbd *api.RBDPersistentVolumeSource, w PrefixWriter) {
|
||||||
|
w.Write(LEVEL_2, "Type:\tRBD (a Rados Block Device mount on the host that shares a pod's lifetime)\n"+
|
||||||
|
" CephMonitors:\t%v\n"+
|
||||||
|
" RBDImage:\t%v\n"+
|
||||||
|
" FSType:\t%v\n"+
|
||||||
|
" RBDPool:\t%v\n"+
|
||||||
|
" RadosUser:\t%v\n"+
|
||||||
|
" Keyring:\t%v\n"+
|
||||||
|
" SecretRef:\t%v\n"+
|
||||||
|
" ReadOnly:\t%v\n",
|
||||||
|
rbd.CephMonitors, rbd.RBDImage, rbd.FSType, rbd.RBDPool, rbd.RadosUser, rbd.Keyring, rbd.SecretRef, rbd.ReadOnly)
|
||||||
|
}
|
||||||
|
|
||||||
func printDownwardAPIVolumeSource(d *api.DownwardAPIVolumeSource, w PrefixWriter) {
|
func printDownwardAPIVolumeSource(d *api.DownwardAPIVolumeSource, w PrefixWriter) {
|
||||||
w.Write(LEVEL_2, "Type:\tDownwardAPI (a volume populated by information about the pod)\n Items:\n")
|
w.Write(LEVEL_2, "Type:\tDownwardAPI (a volume populated by information about the pod)\n Items:\n")
|
||||||
for _, mapping := range d.Items {
|
for _, mapping := range d.Items {
|
||||||
@ -1108,7 +1121,7 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) (
|
|||||||
case pv.Spec.Glusterfs != nil:
|
case pv.Spec.Glusterfs != nil:
|
||||||
printGlusterfsVolumeSource(pv.Spec.Glusterfs, w)
|
printGlusterfsVolumeSource(pv.Spec.Glusterfs, w)
|
||||||
case pv.Spec.RBD != nil:
|
case pv.Spec.RBD != nil:
|
||||||
printRBDVolumeSource(pv.Spec.RBD, w)
|
printRBDPersistentVolumeSource(pv.Spec.RBD, w)
|
||||||
case pv.Spec.Quobyte != nil:
|
case pv.Spec.Quobyte != nil:
|
||||||
printQuobyteVolumeSource(pv.Spec.Quobyte, w)
|
printQuobyteVolumeSource(pv.Spec.Quobyte, w)
|
||||||
case pv.Spec.VsphereVolume != nil:
|
case pv.Spec.VsphereVolume != nil:
|
||||||
|
@ -776,7 +776,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
|
|||||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||||
Spec: api.PersistentVolumeSpec{
|
Spec: api.PersistentVolumeSpec{
|
||||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||||
RBD: &api.RBDVolumeSource{},
|
RBD: &api.RBDPersistentVolumeSource{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -39,7 +39,7 @@ type diskManager interface {
|
|||||||
// Detaches the disk from the kubelet's host machine.
|
// Detaches the disk from the kubelet's host machine.
|
||||||
DetachDisk(disk rbdUnmounter, mntPath string) error
|
DetachDisk(disk rbdUnmounter, mntPath string) error
|
||||||
// Creates a rbd image
|
// Creates a rbd image
|
||||||
CreateImage(provisioner *rbdVolumeProvisioner) (r *v1.RBDVolumeSource, volumeSizeGB int, err error)
|
CreateImage(provisioner *rbdVolumeProvisioner) (r *v1.RBDPersistentVolumeSource, volumeSizeGB int, err error)
|
||||||
// Deletes a rbd image
|
// Deletes a rbd image
|
||||||
DeleteImage(deleter *rbdVolumeDeleter) error
|
DeleteImage(deleter *rbdVolumeDeleter) error
|
||||||
}
|
}
|
||||||
|
@ -78,15 +78,19 @@ func (plugin *rbdPlugin) GetPluginName() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *rbdPlugin) GetVolumeName(spec *volume.Spec) (string, error) {
|
func (plugin *rbdPlugin) GetVolumeName(spec *volume.Spec) (string, error) {
|
||||||
volumeSource, _, err := getVolumeSource(spec)
|
mon, err := getVolumeSourceMonitors(spec)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
img, err := getVolumeSourceImage(spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
"%v:%v",
|
"%v:%v",
|
||||||
volumeSource.CephMonitors,
|
mon,
|
||||||
volumeSource.RBDImage), nil
|
img), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *rbdPlugin) CanSupport(spec *volume.Spec) bool {
|
func (plugin *rbdPlugin) CanSupport(spec *volume.Spec) bool {
|
||||||
@ -117,55 +121,79 @@ func (plugin *rbdPlugin) GetAccessModes() []v1.PersistentVolumeAccessMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *rbdPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.Mounter, error) {
|
func (plugin *rbdPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.Mounter, error) {
|
||||||
var secret string
|
secretName, secretNs, err := getSecretNameAndNamespace(spec, pod.Namespace)
|
||||||
var err error
|
if err != nil {
|
||||||
source, _ := plugin.getRBDVolumeSource(spec)
|
|
||||||
|
|
||||||
if source.SecretRef != nil {
|
|
||||||
if secret, err = parsePodSecret(pod, source.SecretRef.Name, plugin.host.GetKubeClient()); err != nil {
|
|
||||||
glog.Errorf("Couldn't get secret from %v/%v", pod.Namespace, source.SecretRef)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
secret := ""
|
||||||
|
if len(secretName) > 0 && len(secretNs) > 0 {
|
||||||
|
// if secret is provideded, retrieve it
|
||||||
|
kubeClient := plugin.host.GetKubeClient()
|
||||||
|
if kubeClient == nil {
|
||||||
|
return nil, fmt.Errorf("Cannot get kube client")
|
||||||
|
}
|
||||||
|
secrets, err := kubeClient.Core().Secrets(secretNs).Get(secretName, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Couldn't get secret %v/%v err: %v", secretNs, secretName, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, data := range secrets.Data {
|
||||||
|
secret = string(data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inject real implementations here, test through the internal function.
|
// Inject real implementations here, test through the internal function.
|
||||||
return plugin.newMounterInternal(spec, pod.UID, &RBDUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()), secret)
|
return plugin.newMounterInternal(spec, pod.UID, &RBDUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()), secret)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *rbdPlugin) getRBDVolumeSource(spec *volume.Spec) (*v1.RBDVolumeSource, bool) {
|
|
||||||
// rbd volumes used directly in a pod have a ReadOnly flag set by the pod author.
|
|
||||||
// rbd volumes used as a PersistentVolume gets the ReadOnly flag indirectly through the persistent-claim volume used to mount the PV
|
|
||||||
if spec.Volume != nil && spec.Volume.RBD != nil {
|
|
||||||
return spec.Volume.RBD, spec.Volume.RBD.ReadOnly
|
|
||||||
} else {
|
|
||||||
return spec.PersistentVolume.Spec.RBD, spec.ReadOnly
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *rbdPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID, manager diskManager, mounter mount.Interface, exec mount.Exec, secret string) (volume.Mounter, error) {
|
func (plugin *rbdPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID, manager diskManager, mounter mount.Interface, exec mount.Exec, secret string) (volume.Mounter, error) {
|
||||||
source, readOnly := plugin.getRBDVolumeSource(spec)
|
mon, err := getVolumeSourceMonitors(spec)
|
||||||
pool := source.RBDPool
|
if err != nil {
|
||||||
id := source.RadosUser
|
return nil, err
|
||||||
keyring := source.Keyring
|
}
|
||||||
|
img, err := getVolumeSourceImage(spec)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fstype, err := getVolumeSourceFSType(spec)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pool, err := getVolumeSourcePool(spec)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
id, err := getVolumeSourceUser(spec)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
keyring, err := getVolumeSourceKeyRing(spec)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ro, err := getVolumeSourceReadOnly(spec)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &rbdMounter{
|
return &rbdMounter{
|
||||||
rbd: &rbd{
|
rbd: &rbd{
|
||||||
podUID: podUID,
|
podUID: podUID,
|
||||||
volName: spec.Name(),
|
volName: spec.Name(),
|
||||||
Image: source.RBDImage,
|
Image: img,
|
||||||
Pool: pool,
|
Pool: pool,
|
||||||
ReadOnly: readOnly,
|
ReadOnly: ro,
|
||||||
manager: manager,
|
manager: manager,
|
||||||
mounter: &mount.SafeFormatAndMount{Interface: mounter, Exec: exec},
|
mounter: &mount.SafeFormatAndMount{Interface: mounter, Exec: exec},
|
||||||
exec: exec,
|
exec: exec,
|
||||||
plugin: plugin,
|
plugin: plugin,
|
||||||
MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, spec.Name(), plugin.host)),
|
MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, spec.Name(), plugin.host)),
|
||||||
},
|
},
|
||||||
Mon: source.CephMonitors,
|
Mon: mon,
|
||||||
Id: id,
|
Id: id,
|
||||||
Keyring: keyring,
|
Keyring: keyring,
|
||||||
Secret: secret,
|
Secret: secret,
|
||||||
fsType: source.FSType,
|
fsType: fstype,
|
||||||
mountOptions: volume.MountOptionFromSpec(spec),
|
mountOptions: volume.MountOptionFromSpec(spec),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -289,8 +317,9 @@ func (r *rbdVolumeProvisioner) Provision() (*v1.PersistentVolume, error) {
|
|||||||
var err error
|
var err error
|
||||||
adminSecretName := ""
|
adminSecretName := ""
|
||||||
adminSecretNamespace := rbdDefaultAdminSecretNamespace
|
adminSecretNamespace := rbdDefaultAdminSecretNamespace
|
||||||
secretName := ""
|
|
||||||
secret := ""
|
secret := ""
|
||||||
|
secretName := ""
|
||||||
|
secretNamespace := ""
|
||||||
imageFormat := rbdImageFormat2
|
imageFormat := rbdImageFormat2
|
||||||
fstype := ""
|
fstype := ""
|
||||||
|
|
||||||
@ -313,6 +342,8 @@ func (r *rbdVolumeProvisioner) Provision() (*v1.PersistentVolume, error) {
|
|||||||
r.Pool = v
|
r.Pool = v
|
||||||
case "usersecretname":
|
case "usersecretname":
|
||||||
secretName = v
|
secretName = v
|
||||||
|
case "usersecretnamespace":
|
||||||
|
secretNamespace = v
|
||||||
case "imageformat":
|
case "imageformat":
|
||||||
imageFormat = v
|
imageFormat = v
|
||||||
case "imagefeatures":
|
case "imagefeatures":
|
||||||
@ -370,8 +401,9 @@ func (r *rbdVolumeProvisioner) Provision() (*v1.PersistentVolume, error) {
|
|||||||
glog.Infof("successfully created rbd image %q", image)
|
glog.Infof("successfully created rbd image %q", image)
|
||||||
pv := new(v1.PersistentVolume)
|
pv := new(v1.PersistentVolume)
|
||||||
metav1.SetMetaDataAnnotation(&pv.ObjectMeta, volumehelper.VolumeDynamicallyCreatedByKey, "rbd-dynamic-provisioner")
|
metav1.SetMetaDataAnnotation(&pv.ObjectMeta, volumehelper.VolumeDynamicallyCreatedByKey, "rbd-dynamic-provisioner")
|
||||||
rbd.SecretRef = new(v1.LocalObjectReference)
|
rbd.SecretRef = new(v1.SecretReference)
|
||||||
rbd.SecretRef.Name = secretName
|
rbd.SecretRef.Name = secretName
|
||||||
|
rbd.SecretRef.Namespace = secretNamespace
|
||||||
rbd.RadosUser = r.Id
|
rbd.RadosUser = r.Id
|
||||||
rbd.FSType = fstype
|
rbd.FSType = fstype
|
||||||
pv.Spec.PersistentVolumeSource.RBD = rbd
|
pv.Spec.PersistentVolumeSource.RBD = rbd
|
||||||
@ -486,16 +518,83 @@ func (c *rbdUnmounter) TearDownAt(dir string) error {
|
|||||||
return diskTearDown(c.manager, *c, dir, c.mounter)
|
return diskTearDown(c.manager, *c, dir, c.mounter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getVolumeSource(
|
func getVolumeSourceMonitors(spec *volume.Spec) ([]string, error) {
|
||||||
spec *volume.Spec) (*v1.RBDVolumeSource, bool, error) {
|
|
||||||
if spec.Volume != nil && spec.Volume.RBD != nil {
|
if spec.Volume != nil && spec.Volume.RBD != nil {
|
||||||
return spec.Volume.RBD, spec.Volume.RBD.ReadOnly, nil
|
return spec.Volume.RBD.CephMonitors, nil
|
||||||
} else if spec.PersistentVolume != nil &&
|
} else if spec.PersistentVolume != nil &&
|
||||||
spec.PersistentVolume.Spec.RBD != nil {
|
spec.PersistentVolume.Spec.RBD != nil {
|
||||||
return spec.PersistentVolume.Spec.RBD, spec.ReadOnly, nil
|
return spec.PersistentVolume.Spec.RBD.CephMonitors, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, false, fmt.Errorf("Spec does not reference a RBD volume type")
|
return nil, fmt.Errorf("Spec does not reference a RBD volume type")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getVolumeSourceImage(spec *volume.Spec) (string, error) {
|
||||||
|
if spec.Volume != nil && spec.Volume.RBD != nil {
|
||||||
|
return spec.Volume.RBD.RBDImage, nil
|
||||||
|
} else if spec.PersistentVolume != nil &&
|
||||||
|
spec.PersistentVolume.Spec.RBD != nil {
|
||||||
|
return spec.PersistentVolume.Spec.RBD.RBDImage, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("Spec does not reference a RBD volume type")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getVolumeSourceFSType(spec *volume.Spec) (string, error) {
|
||||||
|
if spec.Volume != nil && spec.Volume.RBD != nil {
|
||||||
|
return spec.Volume.RBD.FSType, nil
|
||||||
|
} else if spec.PersistentVolume != nil &&
|
||||||
|
spec.PersistentVolume.Spec.RBD != nil {
|
||||||
|
return spec.PersistentVolume.Spec.RBD.FSType, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("Spec does not reference a RBD volume type")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getVolumeSourcePool(spec *volume.Spec) (string, error) {
|
||||||
|
if spec.Volume != nil && spec.Volume.RBD != nil {
|
||||||
|
return spec.Volume.RBD.RBDPool, nil
|
||||||
|
} else if spec.PersistentVolume != nil &&
|
||||||
|
spec.PersistentVolume.Spec.RBD != nil {
|
||||||
|
return spec.PersistentVolume.Spec.RBD.RBDPool, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("Spec does not reference a RBD volume type")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getVolumeSourceUser(spec *volume.Spec) (string, error) {
|
||||||
|
if spec.Volume != nil && spec.Volume.RBD != nil {
|
||||||
|
return spec.Volume.RBD.RadosUser, nil
|
||||||
|
} else if spec.PersistentVolume != nil &&
|
||||||
|
spec.PersistentVolume.Spec.RBD != nil {
|
||||||
|
return spec.PersistentVolume.Spec.RBD.RadosUser, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("Spec does not reference a RBD volume type")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getVolumeSourceKeyRing(spec *volume.Spec) (string, error) {
|
||||||
|
if spec.Volume != nil && spec.Volume.RBD != nil {
|
||||||
|
return spec.Volume.RBD.Keyring, nil
|
||||||
|
} else if spec.PersistentVolume != nil &&
|
||||||
|
spec.PersistentVolume.Spec.RBD != nil {
|
||||||
|
return spec.PersistentVolume.Spec.RBD.Keyring, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("Spec does not reference a RBD volume type")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getVolumeSourceReadOnly(spec *volume.Spec) (bool, error) {
|
||||||
|
if spec.Volume != nil && spec.Volume.RBD != nil {
|
||||||
|
return spec.Volume.RBD.ReadOnly, nil
|
||||||
|
} else if spec.PersistentVolume != nil &&
|
||||||
|
spec.PersistentVolume.Spec.RBD != nil {
|
||||||
|
// rbd volumes used as a PersistentVolume gets the ReadOnly flag indirectly through
|
||||||
|
// the persistent-claim volume used to mount the PV
|
||||||
|
return spec.ReadOnly, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, fmt.Errorf("Spec does not reference a RBD volume type")
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePodSecret(pod *v1.Pod, secretName string, kubeClient clientset.Interface) (string, error) {
|
func parsePodSecret(pod *v1.Pod, secretName string, kubeClient clientset.Interface) (string, error) {
|
||||||
@ -531,3 +630,26 @@ func parseSecretMap(secretMap map[string]string) (string, error) {
|
|||||||
// If not found, the last secret in the map wins as done before
|
// If not found, the last secret in the map wins as done before
|
||||||
return secret, nil
|
return secret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getSecretNameAndNamespace(spec *volume.Spec, defaultNamespace string) (string, string, error) {
|
||||||
|
if spec.Volume != nil && spec.Volume.RBD != nil {
|
||||||
|
localSecretRef := spec.Volume.RBD.SecretRef
|
||||||
|
if localSecretRef != nil {
|
||||||
|
return localSecretRef.Name, defaultNamespace, nil
|
||||||
|
}
|
||||||
|
return "", "", nil
|
||||||
|
|
||||||
|
} else if spec.PersistentVolume != nil &&
|
||||||
|
spec.PersistentVolume.Spec.RBD != nil {
|
||||||
|
secretRef := spec.PersistentVolume.Spec.RBD.SecretRef
|
||||||
|
secretNs := defaultNamespace
|
||||||
|
if secretRef != nil {
|
||||||
|
if len(secretRef.Namespace) != 0 {
|
||||||
|
secretNs = secretRef.Namespace
|
||||||
|
}
|
||||||
|
return secretRef.Name, secretNs, nil
|
||||||
|
}
|
||||||
|
return "", "", nil
|
||||||
|
}
|
||||||
|
return "", "", fmt.Errorf("Spec does not reference an RBD volume type")
|
||||||
|
}
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -92,7 +93,7 @@ func (fake *fakeDiskManager) DetachDisk(c rbdUnmounter, mntPath string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fake *fakeDiskManager) CreateImage(provisioner *rbdVolumeProvisioner) (r *v1.RBDVolumeSource, volumeSizeGB int, err error) {
|
func (fake *fakeDiskManager) CreateImage(provisioner *rbdVolumeProvisioner) (r *v1.RBDPersistentVolumeSource, volumeSizeGB int, err error) {
|
||||||
return nil, 0, fmt.Errorf("not implemented")
|
return nil, 0, fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +181,7 @@ func TestPluginPersistentVolume(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Spec: v1.PersistentVolumeSpec{
|
Spec: v1.PersistentVolumeSpec{
|
||||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||||
RBD: &v1.RBDVolumeSource{
|
RBD: &v1.RBDPersistentVolumeSource{
|
||||||
CephMonitors: []string{"a", "b"},
|
CephMonitors: []string{"a", "b"},
|
||||||
RBDImage: "bar",
|
RBDImage: "bar",
|
||||||
FSType: "ext4",
|
FSType: "ext4",
|
||||||
@ -205,7 +206,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Spec: v1.PersistentVolumeSpec{
|
Spec: v1.PersistentVolumeSpec{
|
||||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||||
RBD: &v1.RBDVolumeSource{
|
RBD: &v1.RBDPersistentVolumeSource{
|
||||||
CephMonitors: []string{"a", "b"},
|
CephMonitors: []string{"a", "b"},
|
||||||
RBDImage: "bar",
|
RBDImage: "bar",
|
||||||
FSType: "ext4",
|
FSType: "ext4",
|
||||||
@ -329,3 +330,35 @@ func TestPersistAndLoadRBD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetSecretNameAndNamespace(t *testing.T) {
|
||||||
|
secretName := "test-secret-name"
|
||||||
|
secretNamespace := "test-secret-namespace"
|
||||||
|
|
||||||
|
volSpec := &volume.Spec{
|
||||||
|
PersistentVolume: &v1.PersistentVolume{
|
||||||
|
Spec: v1.PersistentVolumeSpec{
|
||||||
|
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||||
|
RBD: &v1.RBDPersistentVolumeSource{
|
||||||
|
CephMonitors: []string{"a", "b"},
|
||||||
|
RBDImage: "bar",
|
||||||
|
FSType: "ext4",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
secretRef := new(v1.SecretReference)
|
||||||
|
secretRef.Name = secretName
|
||||||
|
secretRef.Namespace = secretNamespace
|
||||||
|
volSpec.PersistentVolume.Spec.PersistentVolumeSource.RBD.SecretRef = secretRef
|
||||||
|
|
||||||
|
foundSecretName, foundSecretNamespace, err := getSecretNameAndNamespace(volSpec, "default")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("getSecretNameAndNamespace failed to get Secret's name and namespace: %v", err)
|
||||||
|
}
|
||||||
|
if strings.Compare(secretName, foundSecretName) != 0 || strings.Compare(secretNamespace, foundSecretNamespace) != 0 {
|
||||||
|
t.Errorf("getSecretNameAndNamespace returned incorrect values, expected %s and %s but got %s and %s", secretName, secretNamespace, foundSecretName, foundSecretNamespace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -362,7 +362,7 @@ func (util *RBDUtil) DetachDisk(c rbdUnmounter, mntPath string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (util *RBDUtil) CreateImage(p *rbdVolumeProvisioner) (r *v1.RBDVolumeSource, size int, err error) {
|
func (util *RBDUtil) CreateImage(p *rbdVolumeProvisioner) (r *v1.RBDPersistentVolumeSource, size int, err error) {
|
||||||
var output []byte
|
var output []byte
|
||||||
capacity := p.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
|
capacity := p.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
|
||||||
volSizeBytes := capacity.Value()
|
volSizeBytes := capacity.Value()
|
||||||
@ -400,7 +400,7 @@ func (util *RBDUtil) CreateImage(p *rbdVolumeProvisioner) (r *v1.RBDVolumeSource
|
|||||||
return nil, 0, fmt.Errorf("failed to create rbd image: %v, command output: %s", err, string(output))
|
return nil, 0, fmt.Errorf("failed to create rbd image: %v, command output: %s", err, string(output))
|
||||||
}
|
}
|
||||||
|
|
||||||
return &v1.RBDVolumeSource{
|
return &v1.RBDPersistentVolumeSource{
|
||||||
CephMonitors: p.rbdMounter.Mon,
|
CephMonitors: p.rbdMounter.Mon,
|
||||||
RBDImage: p.rbdMounter.Image,
|
RBDImage: p.rbdMounter.Image,
|
||||||
RBDPool: p.rbdMounter.Pool,
|
RBDPool: p.rbdMounter.Pool,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2287,7 +2287,7 @@ message PersistentVolumeSource {
|
|||||||
// RBD represents a Rados Block Device mount on the host that shares a pod's lifetime.
|
// RBD represents a Rados Block Device mount on the host that shares a pod's lifetime.
|
||||||
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md
|
||||||
// +optional
|
// +optional
|
||||||
optional RBDVolumeSource rbd = 6;
|
optional RBDPersistentVolumeSource rbd = 6;
|
||||||
|
|
||||||
// ISCSI represents an ISCSI Disk resource that is attached to a
|
// ISCSI represents an ISCSI Disk resource that is attached to a
|
||||||
// kubelet's host machine and then exposed to the pod. Provisioned by an admin.
|
// kubelet's host machine and then exposed to the pod. Provisioned by an admin.
|
||||||
@ -3157,6 +3157,57 @@ message QuobyteVolumeSource {
|
|||||||
optional string group = 5;
|
optional string group = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Represents a Rados Block Device mount that lasts the lifetime of a pod.
|
||||||
|
// RBD volumes support ownership management and SELinux relabeling.
|
||||||
|
message RBDPersistentVolumeSource {
|
||||||
|
// A collection of Ceph monitors.
|
||||||
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
|
||||||
|
repeated string monitors = 1;
|
||||||
|
|
||||||
|
// The rados image name.
|
||||||
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
|
||||||
|
optional string image = 2;
|
||||||
|
|
||||||
|
// Filesystem type of the volume that you want to mount.
|
||||||
|
// Tip: Ensure that the filesystem type is supported by the host operating system.
|
||||||
|
// Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified.
|
||||||
|
// More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd
|
||||||
|
// TODO: how do we prevent errors in the filesystem from compromising the machine
|
||||||
|
// +optional
|
||||||
|
optional string fsType = 3;
|
||||||
|
|
||||||
|
// The rados pool name.
|
||||||
|
// Default is rbd.
|
||||||
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
|
||||||
|
// +optional
|
||||||
|
optional string pool = 4;
|
||||||
|
|
||||||
|
// The rados user name.
|
||||||
|
// Default is admin.
|
||||||
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
|
||||||
|
// +optional
|
||||||
|
optional string user = 5;
|
||||||
|
|
||||||
|
// Keyring is the path to key ring for RBDUser.
|
||||||
|
// Default is /etc/ceph/keyring.
|
||||||
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
|
||||||
|
// +optional
|
||||||
|
optional string keyring = 6;
|
||||||
|
|
||||||
|
// SecretRef is name of the authentication secret for RBDUser. If provided
|
||||||
|
// overrides keyring.
|
||||||
|
// Default is nil.
|
||||||
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
|
||||||
|
// +optional
|
||||||
|
optional SecretReference secretRef = 7;
|
||||||
|
|
||||||
|
// ReadOnly here will force the ReadOnly setting in VolumeMounts.
|
||||||
|
// Defaults to false.
|
||||||
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
|
||||||
|
// +optional
|
||||||
|
optional bool readOnly = 8;
|
||||||
|
}
|
||||||
|
|
||||||
// Represents a Rados Block Device mount that lasts the lifetime of a pod.
|
// Represents a Rados Block Device mount that lasts the lifetime of a pod.
|
||||||
// RBD volumes support ownership management and SELinux relabeling.
|
// RBD volumes support ownership management and SELinux relabeling.
|
||||||
message RBDVolumeSource {
|
message RBDVolumeSource {
|
||||||
|
@ -398,7 +398,7 @@ type PersistentVolumeSource struct {
|
|||||||
// RBD represents a Rados Block Device mount on the host that shares a pod's lifetime.
|
// RBD represents a Rados Block Device mount on the host that shares a pod's lifetime.
|
||||||
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md
|
||||||
// +optional
|
// +optional
|
||||||
RBD *RBDVolumeSource `json:"rbd,omitempty" protobuf:"bytes,6,opt,name=rbd"`
|
RBD *RBDPersistentVolumeSource `json:"rbd,omitempty" protobuf:"bytes,6,opt,name=rbd"`
|
||||||
// ISCSI represents an ISCSI Disk resource that is attached to a
|
// ISCSI represents an ISCSI Disk resource that is attached to a
|
||||||
// kubelet's host machine and then exposed to the pod. Provisioned by an admin.
|
// kubelet's host machine and then exposed to the pod. Provisioned by an admin.
|
||||||
// +optional
|
// +optional
|
||||||
@ -838,6 +838,50 @@ type RBDVolumeSource struct {
|
|||||||
ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,8,opt,name=readOnly"`
|
ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,8,opt,name=readOnly"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Represents a Rados Block Device mount that lasts the lifetime of a pod.
|
||||||
|
// RBD volumes support ownership management and SELinux relabeling.
|
||||||
|
type RBDPersistentVolumeSource struct {
|
||||||
|
// A collection of Ceph monitors.
|
||||||
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
|
||||||
|
CephMonitors []string `json:"monitors" protobuf:"bytes,1,rep,name=monitors"`
|
||||||
|
// The rados image name.
|
||||||
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
|
||||||
|
RBDImage string `json:"image" protobuf:"bytes,2,opt,name=image"`
|
||||||
|
// Filesystem type of the volume that you want to mount.
|
||||||
|
// Tip: Ensure that the filesystem type is supported by the host operating system.
|
||||||
|
// Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified.
|
||||||
|
// More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd
|
||||||
|
// TODO: how do we prevent errors in the filesystem from compromising the machine
|
||||||
|
// +optional
|
||||||
|
FSType string `json:"fsType,omitempty" protobuf:"bytes,3,opt,name=fsType"`
|
||||||
|
// The rados pool name.
|
||||||
|
// Default is rbd.
|
||||||
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
|
||||||
|
// +optional
|
||||||
|
RBDPool string `json:"pool,omitempty" protobuf:"bytes,4,opt,name=pool"`
|
||||||
|
// The rados user name.
|
||||||
|
// Default is admin.
|
||||||
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
|
||||||
|
// +optional
|
||||||
|
RadosUser string `json:"user,omitempty" protobuf:"bytes,5,opt,name=user"`
|
||||||
|
// Keyring is the path to key ring for RBDUser.
|
||||||
|
// Default is /etc/ceph/keyring.
|
||||||
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
|
||||||
|
// +optional
|
||||||
|
Keyring string `json:"keyring,omitempty" protobuf:"bytes,6,opt,name=keyring"`
|
||||||
|
// SecretRef is name of the authentication secret for RBDUser. If provided
|
||||||
|
// overrides keyring.
|
||||||
|
// Default is nil.
|
||||||
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
|
||||||
|
// +optional
|
||||||
|
SecretRef *SecretReference `json:"secretRef,omitempty" protobuf:"bytes,7,opt,name=secretRef"`
|
||||||
|
// ReadOnly here will force the ReadOnly setting in VolumeMounts.
|
||||||
|
// Defaults to false.
|
||||||
|
// More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it
|
||||||
|
// +optional
|
||||||
|
ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,8,opt,name=readOnly"`
|
||||||
|
}
|
||||||
|
|
||||||
// Represents a cinder volume resource in Openstack.
|
// Represents a cinder volume resource in Openstack.
|
||||||
// A Cinder volume must exist before mounting to a container.
|
// A Cinder volume must exist before mounting to a container.
|
||||||
// The volume must also be in the same region as the kubelet.
|
// The volume must also be in the same region as the kubelet.
|
||||||
|
@ -1571,6 +1571,22 @@ func (QuobyteVolumeSource) SwaggerDoc() map[string]string {
|
|||||||
return map_QuobyteVolumeSource
|
return map_QuobyteVolumeSource
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var map_RBDPersistentVolumeSource = map[string]string{
|
||||||
|
"": "Represents a Rados Block Device mount that lasts the lifetime of a pod. RBD volumes support ownership management and SELinux relabeling.",
|
||||||
|
"monitors": "A collection of Ceph monitors. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it",
|
||||||
|
"image": "The rados image name. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it",
|
||||||
|
"fsType": "Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd",
|
||||||
|
"pool": "The rados pool name. Default is rbd. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it",
|
||||||
|
"user": "The rados user name. Default is admin. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it",
|
||||||
|
"keyring": "Keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it",
|
||||||
|
"secretRef": "SecretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it",
|
||||||
|
"readOnly": "ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (RBDPersistentVolumeSource) SwaggerDoc() map[string]string {
|
||||||
|
return map_RBDPersistentVolumeSource
|
||||||
|
}
|
||||||
|
|
||||||
var map_RBDVolumeSource = map[string]string{
|
var map_RBDVolumeSource = map[string]string{
|
||||||
"": "Represents a Rados Block Device mount that lasts the lifetime of a pod. RBD volumes support ownership management and SELinux relabeling.",
|
"": "Represents a Rados Block Device mount that lasts the lifetime of a pod. RBD volumes support ownership management and SELinux relabeling.",
|
||||||
"monitors": "A collection of Ceph monitors. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it",
|
"monitors": "A collection of Ceph monitors. More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it",
|
||||||
|
@ -571,6 +571,10 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
|
|||||||
in.(*QuobyteVolumeSource).DeepCopyInto(out.(*QuobyteVolumeSource))
|
in.(*QuobyteVolumeSource).DeepCopyInto(out.(*QuobyteVolumeSource))
|
||||||
return nil
|
return nil
|
||||||
}, InType: reflect.TypeOf(&QuobyteVolumeSource{})},
|
}, InType: reflect.TypeOf(&QuobyteVolumeSource{})},
|
||||||
|
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||||
|
in.(*RBDPersistentVolumeSource).DeepCopyInto(out.(*RBDPersistentVolumeSource))
|
||||||
|
return nil
|
||||||
|
}, InType: reflect.TypeOf(&RBDPersistentVolumeSource{})},
|
||||||
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
|
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||||
in.(*RBDVolumeSource).DeepCopyInto(out.(*RBDVolumeSource))
|
in.(*RBDVolumeSource).DeepCopyInto(out.(*RBDVolumeSource))
|
||||||
return nil
|
return nil
|
||||||
@ -3733,7 +3737,7 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) {
|
|||||||
if *in == nil {
|
if *in == nil {
|
||||||
*out = nil
|
*out = nil
|
||||||
} else {
|
} else {
|
||||||
*out = new(RBDVolumeSource)
|
*out = new(RBDPersistentVolumeSource)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4801,6 +4805,36 @@ func (in *QuobyteVolumeSource) DeepCopy() *QuobyteVolumeSource {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *RBDPersistentVolumeSource) DeepCopyInto(out *RBDPersistentVolumeSource) {
|
||||||
|
*out = *in
|
||||||
|
if in.CephMonitors != nil {
|
||||||
|
in, out := &in.CephMonitors, &out.CephMonitors
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
if in.SecretRef != nil {
|
||||||
|
in, out := &in.SecretRef, &out.SecretRef
|
||||||
|
if *in == nil {
|
||||||
|
*out = nil
|
||||||
|
} else {
|
||||||
|
*out = new(SecretReference)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RBDPersistentVolumeSource.
|
||||||
|
func (in *RBDPersistentVolumeSource) DeepCopy() *RBDPersistentVolumeSource {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(RBDPersistentVolumeSource)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *RBDVolumeSource) DeepCopyInto(out *RBDVolumeSource) {
|
func (in *RBDVolumeSource) DeepCopyInto(out *RBDVolumeSource) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
Loading…
Reference in New Issue
Block a user