Merge pull request #49502 from rootfs/cephfs-pv-ns
Automatic merge from submit-queue (batch tested with PRs 50213, 50707, 49502, 51230, 50848) Refactor CephFS PV spec **What this PR does / why we need it**: refactor CephFS Volume Persistent Volume Spec so CephFS 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. **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes https://github.com/kubernetes-incubator/external-storage/issues/309 **Special notes for your reviewer**: @kubernetes/sig-storage-api-reviews **Release note**: ```release-note Allow CephFS PV to specify a namespace for secret ```
This commit is contained in:
		| @@ -58230,6 +58230,41 @@ | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "io.k8s.api.core.v1.CephFSPersistentVolumeSource": { | ||||
|     "description": "Represents a Ceph Filesystem mount that lasts the lifetime of a pod Cephfs volumes do not support ownership management or SELinux relabeling.", | ||||
|     "required": [ | ||||
|      "monitors" | ||||
|     ], | ||||
|     "properties": { | ||||
|      "monitors": { | ||||
|       "description": "Required: Monitors is a collection of Ceph monitors More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", | ||||
|       "type": "array", | ||||
|       "items": { | ||||
|        "type": "string" | ||||
|       } | ||||
|      }, | ||||
|      "path": { | ||||
|       "description": "Optional: Used as the mounted root, rather than the full Ceph tree, default is /", | ||||
|       "type": "string" | ||||
|      }, | ||||
|      "readOnly": { | ||||
|       "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", | ||||
|       "type": "boolean" | ||||
|      }, | ||||
|      "secretFile": { | ||||
|       "description": "Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", | ||||
|       "type": "string" | ||||
|      }, | ||||
|      "secretRef": { | ||||
|       "description": "Optional: SecretRef is reference to the authentication secret for User, default is empty. More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", | ||||
|       "$ref": "#/definitions/io.k8s.api.core.v1.SecretReference" | ||||
|      }, | ||||
|      "user": { | ||||
|       "description": "Optional: User is the rados user name, default is admin More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", | ||||
|       "type": "string" | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "io.k8s.api.core.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.", | ||||
|     "required": [ | ||||
| @@ -60465,7 +60500,7 @@ | ||||
|      }, | ||||
|      "cephfs": { | ||||
|       "description": "CephFS represents a Ceph FS mount on the host that shares a pod's lifetime", | ||||
|       "$ref": "#/definitions/io.k8s.api.core.v1.CephFSVolumeSource" | ||||
|       "$ref": "#/definitions/io.k8s.api.core.v1.CephFSPersistentVolumeSource" | ||||
|      }, | ||||
|      "cinder": { | ||||
|       "description": "Cinder represents a cinder volume attached and mounted on kubelets host machine More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", | ||||
| @@ -61723,6 +61758,19 @@ | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "io.k8s.api.core.v1.SecretReference": { | ||||
|     "description": "SecretReference represents a Secret Reference. It has enough information to retrieve secret in any namespace", | ||||
|     "properties": { | ||||
|      "name": { | ||||
|       "description": "Name is unique within a namespace to reference a secret resource.", | ||||
|       "type": "string" | ||||
|      }, | ||||
|      "namespace": { | ||||
|       "description": "Namespace defines the space within which the secret name must be unique.", | ||||
|       "type": "string" | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "io.k8s.api.core.v1.SecretVolumeSource": { | ||||
|     "description": "Adapts a Secret into a volume.\n\nThe contents of the target Secret's Data field will be presented in a volume as files using the keys in the Data field as the file names. Secret volumes support ownership management and SELinux relabeling.", | ||||
|     "properties": { | ||||
|   | ||||
| @@ -18865,7 +18865,7 @@ | ||||
|       "description": "Cinder represents a cinder volume attached and mounted on kubelets host machine More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md" | ||||
|      }, | ||||
|      "cephfs": { | ||||
|       "$ref": "v1.CephFSVolumeSource", | ||||
|       "$ref": "v1.CephFSPersistentVolumeSource", | ||||
|       "description": "CephFS represents a Ceph FS mount on the host that shares a pod's lifetime" | ||||
|      }, | ||||
|      "fc": { | ||||
| @@ -19189,8 +19189,8 @@ | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "v1.CephFSVolumeSource": { | ||||
|     "id": "v1.CephFSVolumeSource", | ||||
|    "v1.CephFSPersistentVolumeSource": { | ||||
|     "id": "v1.CephFSPersistentVolumeSource", | ||||
|     "description": "Represents a Ceph Filesystem mount that lasts the lifetime of a pod Cephfs volumes do not support ownership management or SELinux relabeling.", | ||||
|     "required": [ | ||||
|      "monitors" | ||||
| @@ -19216,7 +19216,7 @@ | ||||
|       "description": "Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it" | ||||
|      }, | ||||
|      "secretRef": { | ||||
|       "$ref": "v1.LocalObjectReference", | ||||
|       "$ref": "v1.SecretReference", | ||||
|       "description": "Optional: SecretRef is reference to the authentication secret for User, default is empty. More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it" | ||||
|      }, | ||||
|      "readOnly": { | ||||
| @@ -19225,6 +19225,20 @@ | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "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": { | ||||
|     "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.", | ||||
| @@ -19977,6 +19991,42 @@ | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "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.", | ||||
|     "required": [ | ||||
|      "monitors" | ||||
|     ], | ||||
|     "properties": { | ||||
|      "monitors": { | ||||
|       "type": "array", | ||||
|       "items": { | ||||
|        "type": "string" | ||||
|       }, | ||||
|       "description": "Required: Monitors is a collection of Ceph monitors More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it" | ||||
|      }, | ||||
|      "path": { | ||||
|       "type": "string", | ||||
|       "description": "Optional: Used as the mounted root, rather than the full Ceph tree, default is /" | ||||
|      }, | ||||
|      "user": { | ||||
|       "type": "string", | ||||
|       "description": "Optional: User is the rados user name, default is admin More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it" | ||||
|      }, | ||||
|      "secretFile": { | ||||
|       "type": "string", | ||||
|       "description": "Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it" | ||||
|      }, | ||||
|      "secretRef": { | ||||
|       "$ref": "v1.LocalObjectReference", | ||||
|       "description": "Optional: SecretRef is reference to the authentication secret for User, default is empty. More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it" | ||||
|      }, | ||||
|      "readOnly": { | ||||
|       "type": "boolean", | ||||
|       "description": "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it" | ||||
|      } | ||||
|     } | ||||
|    }, | ||||
|    "v1.DownwardAPIVolumeSource": { | ||||
|     "id": "v1.DownwardAPIVolumeSource", | ||||
|     "description": "DownwardAPIVolumeSource represents a volume containing downward API info. Downward API volumes support ownership management and SELinux relabeling.", | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
|  | ||||
| package(default_visibility = ["//visibility:public"]) | ||||
|  | ||||
| load("@io_bazel_rules_go//go:def.bzl", "go_prefix") | ||||
| load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_prefix") | ||||
| load("@io_kubernetes_build//defs:build.bzl", "gcs_upload") | ||||
|  | ||||
| go_prefix("k8s.io/kubernetes") | ||||
| @@ -457,3 +457,26 @@ genrule( | ||||
|     cmd = "grep ^STABLE_BUILD_SCM_REVISION bazel-out/stable-status.txt | awk '{print $$2}' >$@", | ||||
|     stamp = 1, | ||||
| ) | ||||
|  | ||||
| go_library( | ||||
|     name = "go_default_library", | ||||
|     srcs = [ | ||||
|         "generated.pb.go", | ||||
|         "types.go", | ||||
|     ], | ||||
|     deps = [ | ||||
|         "//vendor/github.com/gogo/protobuf/proto:go_default_library", | ||||
|         "//vendor/github.com/gogo/protobuf/sortkeys:go_default_library", | ||||
|         "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", | ||||
|         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", | ||||
|         "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", | ||||
|         "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", | ||||
|         "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", | ||||
|     ], | ||||
| ) | ||||
|  | ||||
| filegroup( | ||||
|     name = "go_default_library_protos", | ||||
|     srcs = ["generated.proto"], | ||||
|     visibility = ["//visibility:public"], | ||||
| ) | ||||
|   | ||||
| @@ -2378,6 +2378,47 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; } | ||||
| </tbody> | ||||
| </table> | ||||
| 
 | ||||
| </div> | ||||
| <div class="sect2"> | ||||
| <h3 id="_v1_secretreference">v1.SecretReference</h3> | ||||
| <div class="paragraph"> | ||||
| <p>SecretReference represents a Secret Reference. It has enough information to retrieve secret in any namespace</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">name</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">Name is unique within a namespace to reference a secret resource.</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">namespace</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">Namespace defines the space within which the secret name must be unique.</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td> | ||||
| <td class="tableblock halign-left valign-top"></td> | ||||
| </tr> | ||||
| </tbody> | ||||
| </table> | ||||
| 
 | ||||
| </div> | ||||
| <div class="sect2"> | ||||
| <h3 id="_v1_objectmeta">v1.ObjectMeta</h3> | ||||
| @@ -4847,6 +4888,75 @@ The resulting set of endpoints can be viewed as:<br> | ||||
| </tbody> | ||||
| </table> | ||||
| 
 | ||||
| </div> | ||||
| <div class="sect2"> | ||||
| <h3 id="_v1_cephfspersistentvolumesource">v1.CephFSPersistentVolumeSource</h3> | ||||
| <div class="paragraph"> | ||||
| <p>Represents a Ceph Filesystem mount that lasts the lifetime of a pod Cephfs volumes do not support ownership management or SELinux relabeling.</p> | ||||
| </div> | ||||
| <table class="tableblock frame-all grid-all" style="width:100%; "> | ||||
| <colgroup> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;"> | ||||
| <col style="width:20%;">  | ||||
| </colgroup> | ||||
| <thead> | ||||
| <tr> | ||||
| <th class="tableblock halign-left valign-top">Name</th> | ||||
| <th class="tableblock halign-left valign-top">Description</th> | ||||
| <th class="tableblock halign-left valign-top">Required</th> | ||||
| <th class="tableblock halign-left valign-top">Schema</th> | ||||
| <th class="tableblock halign-left valign-top">Default</th> | ||||
| </tr> | ||||
| </thead> | ||||
| <tbody> | ||||
| <tr> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">monitors</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">Required: Monitors is a collection of Ceph monitors More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it">https://releases.k8s.io/HEAD/examples/volumes/cephfs/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">path</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">Optional: Used as the mounted root, rather than the full Ceph tree, default is /</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">Optional: User is the rados user name, default is admin More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it">https://releases.k8s.io/HEAD/examples/volumes/cephfs/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">secretFile</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it">https://releases.k8s.io/HEAD/examples/volumes/cephfs/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">Optional: SecretRef is reference to the authentication secret for User, default is empty. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it">https://releases.k8s.io/HEAD/examples/volumes/cephfs/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">Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: <a href="https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it">https://releases.k8s.io/HEAD/examples/volumes/cephfs/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 class="sect2"> | ||||
| <h3 id="_v1_secretkeyselector">v1.SecretKeySelector</h3> | ||||
| @@ -7419,7 +7529,7 @@ Examples:<br> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">cephfs</p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock">CephFS represents a Ceph FS mount on the host that shares a pod’s lifetime</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_cephfsvolumesource">v1.CephFSVolumeSource</a></p></td> | ||||
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_cephfspersistentvolumesource">v1.CephFSPersistentVolumeSource</a></p></td> | ||||
| <td class="tableblock halign-left valign-top"></td> | ||||
| </tr> | ||||
| <tr> | ||||
|   | ||||
| @@ -48,9 +48,17 @@ func VisitPVSecretNames(pv *api.PersistentVolume, visitor Visitor) bool { | ||||
| 		} | ||||
| 		return true | ||||
| 	case source.CephFS != nil: | ||||
| 		if source.CephFS.SecretRef != nil && !visitor(getClaimRefNamespace(pv), source.CephFS.SecretRef.Name) { | ||||
| 		if source.CephFS.SecretRef != nil { | ||||
| 			// previously persisted PV objects use claimRef namespace | ||||
| 			ns := getClaimRefNamespace(pv) | ||||
| 			if len(source.CephFS.SecretRef.Namespace) > 0 { | ||||
| 				// use the secret namespace if namespace is set | ||||
| 				ns = source.CephFS.SecretRef.Namespace | ||||
| 			} | ||||
| 			if !visitor(ns, source.CephFS.SecretRef.Name) { | ||||
| 				return false | ||||
| 			} | ||||
| 		} | ||||
| 	case source.FlexVolume != nil: | ||||
| 		if source.FlexVolume.SecretRef != nil && !visitor(getClaimRefNamespace(pv), source.FlexVolume.SecretRef.Name) { | ||||
| 			return false | ||||
|   | ||||
| @@ -46,8 +46,15 @@ func TestPVSecrets(t *testing.T) { | ||||
| 		{Spec: api.PersistentVolumeSpec{ | ||||
| 			ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"}, | ||||
| 			PersistentVolumeSource: api.PersistentVolumeSource{ | ||||
| 				CephFS: &api.CephFSVolumeSource{ | ||||
| 					SecretRef: &api.LocalObjectReference{ | ||||
| 				CephFS: &api.CephFSPersistentVolumeSource{ | ||||
| 					SecretRef: &api.SecretReference{ | ||||
| 						Name:      "Spec.PersistentVolumeSource.CephFS.SecretRef", | ||||
| 						Namespace: "cephfs"}}}}}, | ||||
| 		{Spec: api.PersistentVolumeSpec{ | ||||
| 			ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"}, | ||||
| 			PersistentVolumeSource: api.PersistentVolumeSource{ | ||||
| 				CephFS: &api.CephFSPersistentVolumeSource{ | ||||
| 					SecretRef: &api.SecretReference{ | ||||
| 						Name: "Spec.PersistentVolumeSource.CephFS.SecretRef"}}}}}, | ||||
| 		{Spec: api.PersistentVolumeSpec{ | ||||
| 			ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"}, | ||||
| @@ -81,7 +88,6 @@ func TestPVSecrets(t *testing.T) { | ||||
| 						Name:      "Spec.PersistentVolumeSource.StorageOS.SecretRef", | ||||
| 						Namespace: "storageosns"}}}}}, | ||||
| 	} | ||||
|  | ||||
| 	extractedNames := sets.NewString() | ||||
| 	extractedNamesWithNamespace := sets.NewString() | ||||
| 	for _, pv := range pvs { | ||||
| @@ -132,6 +138,7 @@ func TestPVSecrets(t *testing.T) { | ||||
| 		"claimrefns/Spec.PersistentVolumeSource.AzureFile.SecretName", | ||||
| 		"Spec.PersistentVolumeSource.AzureFile.SecretNamespace/Spec.PersistentVolumeSource.AzureFile.SecretName", | ||||
| 		"claimrefns/Spec.PersistentVolumeSource.CephFS.SecretRef", | ||||
| 		"cephfs/Spec.PersistentVolumeSource.CephFS.SecretRef", | ||||
| 		"claimrefns/Spec.PersistentVolumeSource.FlexVolume.SecretRef", | ||||
| 		"claimrefns/Spec.PersistentVolumeSource.RBD.SecretRef", | ||||
| 		"claimrefns/Spec.PersistentVolumeSource.ScaleIO.SecretRef", | ||||
|   | ||||
| @@ -360,7 +360,7 @@ type PersistentVolumeSource struct { | ||||
| 	Cinder *CinderVolumeSource | ||||
| 	// CephFS represents a Ceph FS mount on the host that shares a pod's lifetime | ||||
| 	// +optional | ||||
| 	CephFS *CephFSVolumeSource | ||||
| 	CephFS *CephFSPersistentVolumeSource | ||||
| 	// FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod. | ||||
| 	// +optional | ||||
| 	FC *FCVolumeSource | ||||
| @@ -1019,6 +1019,40 @@ type CephFSVolumeSource struct { | ||||
| 	ReadOnly bool | ||||
| } | ||||
|  | ||||
| // SecretReference represents a Secret Reference. It has enough information to retrieve secret | ||||
| // in any namespace | ||||
| type SecretReference struct { | ||||
| 	// Name is unique within a namespace to reference a secret resource. | ||||
| 	// +optional | ||||
| 	Name string | ||||
| 	// Namespace defines the space within which the secret name must be unique. | ||||
| 	// +optional | ||||
| 	Namespace string | ||||
| } | ||||
|  | ||||
| // Represents a Ceph Filesystem mount that lasts the lifetime of a pod | ||||
| // Cephfs volumes do not support ownership management or SELinux relabeling. | ||||
| type CephFSPersistentVolumeSource struct { | ||||
| 	// Required: Monitors is a collection of Ceph monitors | ||||
| 	Monitors []string | ||||
| 	// Optional: Used as the mounted root, rather than the full Ceph tree, default is / | ||||
| 	// +optional | ||||
| 	Path string | ||||
| 	// Optional: User is the rados user name, default is admin | ||||
| 	// +optional | ||||
| 	User string | ||||
| 	// Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret | ||||
| 	// +optional | ||||
| 	SecretFile 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 Flocker volume mounted by the Flocker agent. | ||||
| // One and only one of datasetName and datasetUUID should be set. | ||||
| // Flocker volumes do not support ownership management or SELinux relabeling. | ||||
|   | ||||
| @@ -56,6 +56,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { | ||||
| 		Convert_api_Binding_To_v1_Binding, | ||||
| 		Convert_v1_Capabilities_To_api_Capabilities, | ||||
| 		Convert_api_Capabilities_To_v1_Capabilities, | ||||
| 		Convert_v1_CephFSPersistentVolumeSource_To_api_CephFSPersistentVolumeSource, | ||||
| 		Convert_api_CephFSPersistentVolumeSource_To_v1_CephFSPersistentVolumeSource, | ||||
| 		Convert_v1_CephFSVolumeSource_To_api_CephFSVolumeSource, | ||||
| 		Convert_api_CephFSVolumeSource_To_v1_CephFSVolumeSource, | ||||
| 		Convert_v1_CinderVolumeSource_To_api_CinderVolumeSource, | ||||
| @@ -338,6 +340,8 @@ func RegisterConversions(scheme *runtime.Scheme) error { | ||||
| 		Convert_api_SecretList_To_v1_SecretList, | ||||
| 		Convert_v1_SecretProjection_To_api_SecretProjection, | ||||
| 		Convert_api_SecretProjection_To_v1_SecretProjection, | ||||
| 		Convert_v1_SecretReference_To_api_SecretReference, | ||||
| 		Convert_api_SecretReference_To_v1_SecretReference, | ||||
| 		Convert_v1_SecretVolumeSource_To_api_SecretVolumeSource, | ||||
| 		Convert_api_SecretVolumeSource_To_v1_SecretVolumeSource, | ||||
| 		Convert_v1_SecurityContext_To_api_SecurityContext, | ||||
| @@ -607,6 +611,40 @@ func Convert_api_Capabilities_To_v1_Capabilities(in *api.Capabilities, out *v1.C | ||||
| 	return autoConvert_api_Capabilities_To_v1_Capabilities(in, out, s) | ||||
| } | ||||
| 
 | ||||
| func autoConvert_v1_CephFSPersistentVolumeSource_To_api_CephFSPersistentVolumeSource(in *v1.CephFSPersistentVolumeSource, out *api.CephFSPersistentVolumeSource, s conversion.Scope) error { | ||||
| 	out.Monitors = *(*[]string)(unsafe.Pointer(&in.Monitors)) | ||||
| 	out.Path = in.Path | ||||
| 	out.User = in.User | ||||
| 	out.SecretFile = in.SecretFile | ||||
| 	out.SecretRef = (*api.SecretReference)(unsafe.Pointer(in.SecretRef)) | ||||
| 	out.ReadOnly = in.ReadOnly | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Convert_v1_CephFSPersistentVolumeSource_To_api_CephFSPersistentVolumeSource is an autogenerated conversion function. | ||||
| func Convert_v1_CephFSPersistentVolumeSource_To_api_CephFSPersistentVolumeSource(in *v1.CephFSPersistentVolumeSource, out *api.CephFSPersistentVolumeSource, s conversion.Scope) error { | ||||
| 	return autoConvert_v1_CephFSPersistentVolumeSource_To_api_CephFSPersistentVolumeSource(in, out, s) | ||||
| } | ||||
| 
 | ||||
| func autoConvert_api_CephFSPersistentVolumeSource_To_v1_CephFSPersistentVolumeSource(in *api.CephFSPersistentVolumeSource, out *v1.CephFSPersistentVolumeSource, s conversion.Scope) error { | ||||
| 	if in.Monitors == nil { | ||||
| 		out.Monitors = make([]string, 0) | ||||
| 	} else { | ||||
| 		out.Monitors = *(*[]string)(unsafe.Pointer(&in.Monitors)) | ||||
| 	} | ||||
| 	out.Path = in.Path | ||||
| 	out.User = in.User | ||||
| 	out.SecretFile = in.SecretFile | ||||
| 	out.SecretRef = (*v1.SecretReference)(unsafe.Pointer(in.SecretRef)) | ||||
| 	out.ReadOnly = in.ReadOnly | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Convert_api_CephFSPersistentVolumeSource_To_v1_CephFSPersistentVolumeSource is an autogenerated conversion function. | ||||
| func Convert_api_CephFSPersistentVolumeSource_To_v1_CephFSPersistentVolumeSource(in *api.CephFSPersistentVolumeSource, out *v1.CephFSPersistentVolumeSource, s conversion.Scope) error { | ||||
| 	return autoConvert_api_CephFSPersistentVolumeSource_To_v1_CephFSPersistentVolumeSource(in, out, s) | ||||
| } | ||||
| 
 | ||||
| func autoConvert_v1_CephFSVolumeSource_To_api_CephFSVolumeSource(in *v1.CephFSVolumeSource, out *api.CephFSVolumeSource, s conversion.Scope) error { | ||||
| 	out.Monitors = *(*[]string)(unsafe.Pointer(&in.Monitors)) | ||||
| 	out.Path = in.Path | ||||
| @@ -3090,7 +3128,7 @@ func autoConvert_v1_PersistentVolumeSource_To_api_PersistentVolumeSource(in *v1. | ||||
| 	out.RBD = (*api.RBDVolumeSource)(unsafe.Pointer(in.RBD)) | ||||
| 	out.ISCSI = (*api.ISCSIVolumeSource)(unsafe.Pointer(in.ISCSI)) | ||||
| 	out.Cinder = (*api.CinderVolumeSource)(unsafe.Pointer(in.Cinder)) | ||||
| 	out.CephFS = (*api.CephFSVolumeSource)(unsafe.Pointer(in.CephFS)) | ||||
| 	out.CephFS = (*api.CephFSPersistentVolumeSource)(unsafe.Pointer(in.CephFS)) | ||||
| 	out.FC = (*api.FCVolumeSource)(unsafe.Pointer(in.FC)) | ||||
| 	out.Flocker = (*api.FlockerVolumeSource)(unsafe.Pointer(in.Flocker)) | ||||
| 	out.FlexVolume = (*api.FlexVolumeSource)(unsafe.Pointer(in.FlexVolume)) | ||||
| @@ -3122,7 +3160,7 @@ func autoConvert_api_PersistentVolumeSource_To_v1_PersistentVolumeSource(in *api | ||||
| 	out.ISCSI = (*v1.ISCSIVolumeSource)(unsafe.Pointer(in.ISCSI)) | ||||
| 	out.FlexVolume = (*v1.FlexVolumeSource)(unsafe.Pointer(in.FlexVolume)) | ||||
| 	out.Cinder = (*v1.CinderVolumeSource)(unsafe.Pointer(in.Cinder)) | ||||
| 	out.CephFS = (*v1.CephFSVolumeSource)(unsafe.Pointer(in.CephFS)) | ||||
| 	out.CephFS = (*v1.CephFSPersistentVolumeSource)(unsafe.Pointer(in.CephFS)) | ||||
| 	out.FC = (*v1.FCVolumeSource)(unsafe.Pointer(in.FC)) | ||||
| 	out.Flocker = (*v1.FlockerVolumeSource)(unsafe.Pointer(in.Flocker)) | ||||
| 	out.AzureFile = (*v1.AzureFilePersistentVolumeSource)(unsafe.Pointer(in.AzureFile)) | ||||
| @@ -4606,6 +4644,28 @@ func Convert_api_SecretProjection_To_v1_SecretProjection(in *api.SecretProjectio | ||||
| 	return autoConvert_api_SecretProjection_To_v1_SecretProjection(in, out, s) | ||||
| } | ||||
| 
 | ||||
| func autoConvert_v1_SecretReference_To_api_SecretReference(in *v1.SecretReference, out *api.SecretReference, s conversion.Scope) error { | ||||
| 	out.Name = in.Name | ||||
| 	out.Namespace = in.Namespace | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Convert_v1_SecretReference_To_api_SecretReference is an autogenerated conversion function. | ||||
| func Convert_v1_SecretReference_To_api_SecretReference(in *v1.SecretReference, out *api.SecretReference, s conversion.Scope) error { | ||||
| 	return autoConvert_v1_SecretReference_To_api_SecretReference(in, out, s) | ||||
| } | ||||
| 
 | ||||
| func autoConvert_api_SecretReference_To_v1_SecretReference(in *api.SecretReference, out *v1.SecretReference, s conversion.Scope) error { | ||||
| 	out.Name = in.Name | ||||
| 	out.Namespace = in.Namespace | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Convert_api_SecretReference_To_v1_SecretReference is an autogenerated conversion function. | ||||
| func Convert_api_SecretReference_To_v1_SecretReference(in *api.SecretReference, out *v1.SecretReference, s conversion.Scope) error { | ||||
| 	return autoConvert_api_SecretReference_To_v1_SecretReference(in, out, s) | ||||
| } | ||||
| 
 | ||||
| func autoConvert_v1_SecretVolumeSource_To_api_SecretVolumeSource(in *v1.SecretVolumeSource, out *api.SecretVolumeSource, s conversion.Scope) error { | ||||
| 	out.SecretName = in.SecretName | ||||
| 	out.Items = *(*[]api.KeyToPath)(unsafe.Pointer(&in.Items)) | ||||
|   | ||||
| @@ -1066,6 +1066,14 @@ func validateCephFSVolumeSource(cephfs *api.CephFSVolumeSource, fldPath *field.P | ||||
| 	return allErrs | ||||
| } | ||||
|  | ||||
| func validateCephFSPersistentVolumeSource(cephfs *api.CephFSPersistentVolumeSource, fldPath *field.Path) field.ErrorList { | ||||
| 	allErrs := field.ErrorList{} | ||||
| 	if len(cephfs.Monitors) == 0 { | ||||
| 		allErrs = append(allErrs, field.Required(fldPath.Child("monitors"), "")) | ||||
| 	} | ||||
| 	return allErrs | ||||
| } | ||||
|  | ||||
| func validateFlexVolumeSource(fv *api.FlexVolumeSource, fldPath *field.Path) field.ErrorList { | ||||
| 	allErrs := field.ErrorList{} | ||||
| 	if len(fv.Driver) == 0 { | ||||
| @@ -1350,7 +1358,7 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) field.ErrorList { | ||||
| 			allErrs = append(allErrs, field.Forbidden(specPath.Child("cephFS"), "may not specify more than 1 volume type")) | ||||
| 		} else { | ||||
| 			numVolumes++ | ||||
| 			allErrs = append(allErrs, validateCephFSVolumeSource(pv.Spec.CephFS, specPath.Child("cephfs"))...) | ||||
| 			allErrs = append(allErrs, validateCephFSPersistentVolumeSource(pv.Spec.CephFS, specPath.Child("cephfs"))...) | ||||
| 		} | ||||
| 	} | ||||
| 	if pv.Spec.ISCSI != nil { | ||||
|   | ||||
| @@ -74,6 +74,10 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { | ||||
| 			in.(*Capabilities).DeepCopyInto(out.(*Capabilities)) | ||||
| 			return nil | ||||
| 		}, InType: reflect.TypeOf(&Capabilities{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { | ||||
| 			in.(*CephFSPersistentVolumeSource).DeepCopyInto(out.(*CephFSPersistentVolumeSource)) | ||||
| 			return nil | ||||
| 		}, InType: reflect.TypeOf(&CephFSPersistentVolumeSource{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { | ||||
| 			in.(*CephFSVolumeSource).DeepCopyInto(out.(*CephFSVolumeSource)) | ||||
| 			return nil | ||||
| @@ -638,6 +642,10 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { | ||||
| 			in.(*SecretProjection).DeepCopyInto(out.(*SecretProjection)) | ||||
| 			return nil | ||||
| 		}, InType: reflect.TypeOf(&SecretProjection{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { | ||||
| 			in.(*SecretReference).DeepCopyInto(out.(*SecretReference)) | ||||
| 			return nil | ||||
| 		}, InType: reflect.TypeOf(&SecretReference{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { | ||||
| 			in.(*SecretVolumeSource).DeepCopyInto(out.(*SecretVolumeSource)) | ||||
| 			return nil | ||||
| @@ -978,6 +986,36 @@ func (in *Capabilities) DeepCopy() *Capabilities { | ||||
| 	return out | ||||
| } | ||||
| 
 | ||||
| // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. | ||||
| func (in *CephFSPersistentVolumeSource) DeepCopyInto(out *CephFSPersistentVolumeSource) { | ||||
| 	*out = *in | ||||
| 	if in.Monitors != nil { | ||||
| 		in, out := &in.Monitors, &out.Monitors | ||||
| 		*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 CephFSPersistentVolumeSource. | ||||
| func (in *CephFSPersistentVolumeSource) DeepCopy() *CephFSPersistentVolumeSource { | ||||
| 	if in == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	out := new(CephFSPersistentVolumeSource) | ||||
| 	in.DeepCopyInto(out) | ||||
| 	return out | ||||
| } | ||||
| 
 | ||||
| // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. | ||||
| func (in *CephFSVolumeSource) DeepCopyInto(out *CephFSVolumeSource) { | ||||
| 	*out = *in | ||||
| @@ -3681,7 +3719,7 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) { | ||||
| 		if *in == nil { | ||||
| 			*out = nil | ||||
| 		} else { | ||||
| 			*out = new(CephFSVolumeSource) | ||||
| 			*out = new(CephFSPersistentVolumeSource) | ||||
| 			(*in).DeepCopyInto(*out) | ||||
| 		} | ||||
| 	} | ||||
| @@ -5263,6 +5301,22 @@ func (in *SecretProjection) DeepCopy() *SecretProjection { | ||||
| 	return out | ||||
| } | ||||
| 
 | ||||
| // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. | ||||
| func (in *SecretReference) DeepCopyInto(out *SecretReference) { | ||||
| 	*out = *in | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretReference. | ||||
| func (in *SecretReference) DeepCopy() *SecretReference { | ||||
| 	if in == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	out := new(SecretReference) | ||||
| 	in.DeepCopyInto(out) | ||||
| 	return out | ||||
| } | ||||
| 
 | ||||
| // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. | ||||
| func (in *SecretVolumeSource) DeepCopyInto(out *SecretVolumeSource) { | ||||
| 	*out = *in | ||||
|   | ||||
| @@ -954,6 +954,17 @@ func printCephFSVolumeSource(cephfs *api.CephFSVolumeSource, w PrefixWriter) { | ||||
| 		cephfs.Monitors, cephfs.Path, cephfs.User, cephfs.SecretFile, cephfs.SecretRef, cephfs.ReadOnly) | ||||
| } | ||||
|  | ||||
| func printCephFSPersistentVolumeSource(cephfs *api.CephFSPersistentVolumeSource, w PrefixWriter) { | ||||
| 	w.Write(LEVEL_2, "Type:\tCephFS (a CephFS mount on the host that shares a pod's lifetime)\n"+ | ||||
| 		"    Monitors:\t%v\n"+ | ||||
| 		"    Path:\t%v\n"+ | ||||
| 		"    User:\t%v\n"+ | ||||
| 		"    SecretFile:\t%v\n"+ | ||||
| 		"    SecretRef:\t%v\n"+ | ||||
| 		"    ReadOnly:\t%v\n", | ||||
| 		cephfs.Monitors, cephfs.Path, cephfs.User, cephfs.SecretFile, cephfs.SecretRef, cephfs.ReadOnly) | ||||
| } | ||||
|  | ||||
| func printStorageOSVolumeSource(storageos *api.StorageOSVolumeSource, w PrefixWriter) { | ||||
| 	w.Write(LEVEL_2, "Type:\tStorageOS (a StorageOS Persistent Disk resource)\n"+ | ||||
| 		"    VolumeName:\t%v\n"+ | ||||
| @@ -1095,7 +1106,7 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) ( | ||||
| 		case pv.Spec.Local != nil: | ||||
| 			printLocalVolumeSource(pv.Spec.Local, w) | ||||
| 		case pv.Spec.CephFS != nil: | ||||
| 			printCephFSVolumeSource(pv.Spec.CephFS, w) | ||||
| 			printCephFSPersistentVolumeSource(pv.Spec.CephFS, w) | ||||
| 		case pv.Spec.StorageOS != nil: | ||||
| 			printStorageOSPersistentVolumeSource(pv.Spec.StorageOS, w) | ||||
| 		case pv.Spec.FC != nil: | ||||
|   | ||||
| @@ -56,12 +56,12 @@ func (plugin *cephfsPlugin) GetPluginName() string { | ||||
| } | ||||
|  | ||||
| func (plugin *cephfsPlugin) GetVolumeName(spec *volume.Spec) (string, error) { | ||||
| 	volumeSource, _, err := getVolumeSource(spec) | ||||
| 	mon, _, _, _, _, err := getVolumeSource(spec) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	return fmt.Sprintf("%v", volumeSource.Monitors), nil | ||||
| 	return fmt.Sprintf("%v", mon), nil | ||||
| } | ||||
|  | ||||
| func (plugin *cephfsPlugin) CanSupport(spec *volume.Spec) bool { | ||||
| @@ -89,23 +89,23 @@ func (plugin *cephfsPlugin) GetAccessModes() []v1.PersistentVolumeAccessMode { | ||||
| } | ||||
|  | ||||
| func (plugin *cephfsPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.Mounter, error) { | ||||
| 	cephvs, _, err := getVolumeSource(spec) | ||||
| 	secretName, secretNs, err := getSecretNameAndNamespace(spec, pod.Namespace) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	secret := "" | ||||
| 	if cephvs.SecretRef != nil { | ||||
| 	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") | ||||
| 		} | ||||
|  | ||||
| 		secretName, err := kubeClient.Core().Secrets(pod.Namespace).Get(cephvs.SecretRef.Name, metav1.GetOptions{}) | ||||
| 		secrets, err := kubeClient.Core().Secrets(secretNs).Get(secretName, metav1.GetOptions{}) | ||||
| 		if err != nil { | ||||
| 			err = fmt.Errorf("Couldn't get secret %v/%v err: %v", pod.Namespace, cephvs.SecretRef, err) | ||||
| 			err = fmt.Errorf("Couldn't get secret %v/%v err: %v", secretNs, secretName, err) | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		for name, data := range secretName.Data { | ||||
| 		for name, data := range secrets.Data { | ||||
| 			secret = string(data) | ||||
| 			glog.V(4).Infof("found ceph secret info: %s", name) | ||||
| 		} | ||||
| @@ -114,37 +114,35 @@ func (plugin *cephfsPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume. | ||||
| } | ||||
|  | ||||
| func (plugin *cephfsPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID, mounter mount.Interface, secret string) (volume.Mounter, error) { | ||||
| 	cephvs, _, err := getVolumeSource(spec) | ||||
| 	mon, path, id, secretFile, readOnly, err := getVolumeSource(spec) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	id := cephvs.User | ||||
| 	if id == "" { | ||||
| 		id = "admin" | ||||
| 	} | ||||
| 	path := cephvs.Path | ||||
| 	if path == "" { | ||||
| 		path = "/" | ||||
| 	} | ||||
| 	if !strings.HasPrefix(path, "/") { | ||||
| 		path = "/" + path | ||||
| 	} | ||||
| 	secret_file := cephvs.SecretFile | ||||
| 	if secret_file == "" { | ||||
| 		secret_file = "/etc/ceph/" + id + ".secret" | ||||
|  | ||||
| 	if secretFile == "" { | ||||
| 		secretFile = "/etc/ceph/" + id + ".secret" | ||||
| 	} | ||||
|  | ||||
| 	return &cephfsMounter{ | ||||
| 		cephfs: &cephfs{ | ||||
| 			podUID:       podUID, | ||||
| 			volName:      spec.Name(), | ||||
| 			mon:          cephvs.Monitors, | ||||
| 			mon:          mon, | ||||
| 			path:         path, | ||||
| 			secret:       secret, | ||||
| 			id:           id, | ||||
| 			secret_file:  secret_file, | ||||
| 			readonly:     cephvs.ReadOnly, | ||||
| 			secret_file:  secretFile, | ||||
| 			readonly:     readOnly, | ||||
| 			mounter:      mounter, | ||||
| 			plugin:       plugin, | ||||
| 			mountOptions: volume.MountOptionFromSpec(spec), | ||||
| @@ -301,13 +299,46 @@ func (cephfsVolume *cephfs) execMount(mountpoint string) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func getVolumeSource(spec *volume.Spec) (*v1.CephFSVolumeSource, bool, error) { | ||||
| func getVolumeSource(spec *volume.Spec) ([]string, string, string, string, bool, error) { | ||||
| 	if spec.Volume != nil && spec.Volume.CephFS != nil { | ||||
| 		return spec.Volume.CephFS, spec.Volume.CephFS.ReadOnly, nil | ||||
| 		mon := spec.Volume.CephFS.Monitors | ||||
| 		path := spec.Volume.CephFS.Path | ||||
| 		user := spec.Volume.CephFS.User | ||||
| 		secretFile := spec.Volume.CephFS.SecretFile | ||||
| 		readOnly := spec.Volume.CephFS.ReadOnly | ||||
| 		return mon, path, user, secretFile, readOnly, nil | ||||
| 	} else if spec.PersistentVolume != nil && | ||||
| 		spec.PersistentVolume.Spec.CephFS != nil { | ||||
| 		return spec.PersistentVolume.Spec.CephFS, spec.ReadOnly, nil | ||||
| 		mon := spec.PersistentVolume.Spec.CephFS.Monitors | ||||
| 		path := spec.PersistentVolume.Spec.CephFS.Path | ||||
| 		user := spec.PersistentVolume.Spec.CephFS.User | ||||
| 		secretFile := spec.PersistentVolume.Spec.CephFS.SecretFile | ||||
| 		readOnly := spec.PersistentVolume.Spec.CephFS.ReadOnly | ||||
| 		return mon, path, user, secretFile, readOnly, nil | ||||
| 	} | ||||
|  | ||||
| 	return nil, false, fmt.Errorf("Spec does not reference a CephFS volume type") | ||||
| 	return nil, "", "", "", false, fmt.Errorf("Spec does not reference a CephFS volume type") | ||||
| } | ||||
|  | ||||
| func getSecretNameAndNamespace(spec *volume.Spec, defaultNamespace string) (string, string, error) { | ||||
| 	if spec.Volume != nil && spec.Volume.CephFS != nil { | ||||
| 		localSecretRef := spec.Volume.CephFS.SecretRef | ||||
| 		if localSecretRef != nil { | ||||
| 			return localSecretRef.Name, defaultNamespace, nil | ||||
| 		} | ||||
| 		return "", "", nil | ||||
|  | ||||
| 	} else if spec.PersistentVolume != nil && | ||||
| 		spec.PersistentVolume.Spec.CephFS != nil { | ||||
| 		secretRef := spec.PersistentVolume.Spec.CephFS.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 CephFS volume type") | ||||
| } | ||||
|   | ||||
| @@ -135,3 +135,94 @@ func TestConstructVolumeSpec(t *testing.T) { | ||||
| 		t.Errorf("Get wrong cephfs spec name, got: %s", cephfsSpec.Name()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type testcase struct { | ||||
| 	name      string | ||||
| 	defaultNs string | ||||
| 	spec      *volume.Spec | ||||
| 	// Expected return of the test | ||||
| 	expectedName  string | ||||
| 	expectedNs    string | ||||
| 	expectedError error | ||||
| } | ||||
|  | ||||
| func TestGetSecretNameAndNamespaceForPV(t *testing.T) { | ||||
| 	tests := []testcase{ | ||||
| 		{ | ||||
| 			name:      "persistent volume source", | ||||
| 			defaultNs: "default", | ||||
| 			spec: &volume.Spec{ | ||||
| 				PersistentVolume: &v1.PersistentVolume{ | ||||
| 					Spec: v1.PersistentVolumeSpec{ | ||||
| 						PersistentVolumeSource: v1.PersistentVolumeSource{ | ||||
| 							CephFS: &v1.CephFSPersistentVolumeSource{ | ||||
| 								Monitors: []string{"a", "b"}, | ||||
| 								User:     "user", | ||||
| 								SecretRef: &v1.SecretReference{ | ||||
| 									Name:      "name", | ||||
| 									Namespace: "ns", | ||||
| 								}, | ||||
| 								SecretFile: "/etc/ceph/user.secret", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectedName:  "name", | ||||
| 			expectedNs:    "ns", | ||||
| 			expectedError: nil, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:      "persistent volume source without namespace", | ||||
| 			defaultNs: "default", | ||||
| 			spec: &volume.Spec{ | ||||
| 				PersistentVolume: &v1.PersistentVolume{ | ||||
| 					Spec: v1.PersistentVolumeSpec{ | ||||
| 						PersistentVolumeSource: v1.PersistentVolumeSource{ | ||||
| 							CephFS: &v1.CephFSPersistentVolumeSource{ | ||||
| 								Monitors: []string{"a", "b"}, | ||||
| 								User:     "user", | ||||
| 								SecretRef: &v1.SecretReference{ | ||||
| 									Name: "name", | ||||
| 								}, | ||||
| 								SecretFile: "/etc/ceph/user.secret", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectedName:  "name", | ||||
| 			expectedNs:    "default", | ||||
| 			expectedError: nil, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:      "pod volume source", | ||||
| 			defaultNs: "default", | ||||
| 			spec: &volume.Spec{ | ||||
| 				Volume: &v1.Volume{ | ||||
| 					VolumeSource: v1.VolumeSource{ | ||||
| 						CephFS: &v1.CephFSVolumeSource{ | ||||
| 							Monitors: []string{"a", "b"}, | ||||
| 							User:     "user", | ||||
| 							SecretRef: &v1.LocalObjectReference{ | ||||
| 								Name: "name", | ||||
| 							}, | ||||
| 							SecretFile: "/etc/ceph/user.secret", | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectedName:  "name", | ||||
| 			expectedNs:    "default", | ||||
| 			expectedError: nil, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, testcase := range tests { | ||||
| 		resultName, resultNs, err := getSecretNameAndNamespace(testcase.spec, testcase.defaultNs) | ||||
| 		if err != testcase.expectedError || resultName != testcase.expectedName || resultNs != testcase.expectedNs { | ||||
| 			t.Errorf("%s failed: expected err=%v ns=%q name=%q, got %v/%q/%q", testcase.name, testcase.expectedError, testcase.expectedNs, testcase.expectedName, | ||||
| 				err, resultNs, resultName) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -180,6 +180,39 @@ message Capabilities { | ||||
|   repeated string drop = 2; | ||||
| } | ||||
| 
 | ||||
| // Represents a Ceph Filesystem mount that lasts the lifetime of a pod | ||||
| // Cephfs volumes do not support ownership management or SELinux relabeling. | ||||
| message CephFSPersistentVolumeSource { | ||||
|   // Required: Monitors is a collection of Ceph monitors | ||||
|   // More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it | ||||
|   repeated string monitors = 1; | ||||
| 
 | ||||
|   // Optional: Used as the mounted root, rather than the full Ceph tree, default is / | ||||
|   // +optional | ||||
|   optional string path = 2; | ||||
| 
 | ||||
|   // Optional: User is the rados user name, default is admin | ||||
|   // More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it | ||||
|   // +optional | ||||
|   optional string user = 3; | ||||
| 
 | ||||
|   // Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret | ||||
|   // More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it | ||||
|   // +optional | ||||
|   optional string secretFile = 4; | ||||
| 
 | ||||
|   // Optional: SecretRef is reference to the authentication secret for User, default is empty. | ||||
|   // More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it | ||||
|   // +optional | ||||
|   optional SecretReference secretRef = 5; | ||||
| 
 | ||||
|   // Optional: Defaults to false (read/write). ReadOnly here will force | ||||
|   // the ReadOnly setting in VolumeMounts. | ||||
|   // More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it | ||||
|   // +optional | ||||
|   optional bool readOnly = 6; | ||||
| } | ||||
| 
 | ||||
| // Represents a Ceph Filesystem mount that lasts the lifetime of a pod | ||||
| // Cephfs volumes do not support ownership management or SELinux relabeling. | ||||
| message CephFSVolumeSource { | ||||
| @@ -2223,7 +2256,7 @@ message PersistentVolumeSource { | ||||
| 
 | ||||
|   // CephFS represents a Ceph FS mount on the host that shares a pod's lifetime | ||||
|   // +optional | ||||
|   optional CephFSVolumeSource cephfs = 9; | ||||
|   optional CephFSPersistentVolumeSource cephfs = 9; | ||||
| 
 | ||||
|   // FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod. | ||||
|   // +optional | ||||
| @@ -3491,6 +3524,18 @@ message SecretProjection { | ||||
|   optional bool optional = 4; | ||||
| } | ||||
| 
 | ||||
| // SecretReference represents a Secret Reference. It has enough information to retrieve secret | ||||
| // in any namespace | ||||
| message SecretReference { | ||||
|   // Name is unique within a namespace to reference a secret resource. | ||||
|   // +optional | ||||
|   optional string name = 1; | ||||
| 
 | ||||
|   // Namespace defines the space within which the secret name must be unique. | ||||
|   // +optional | ||||
|   optional string namespace = 2; | ||||
| } | ||||
| 
 | ||||
| // Adapts a Secret into a volume. | ||||
| //  | ||||
| // The contents of the target Secret's Data field will be presented in a volume | ||||
|   | ||||
| @@ -6069,7 +6069,7 @@ func (x *PersistentVolumeSource) codecDecodeSelfFromMap(l int, d *codec1978.Deco | ||||
| 				} | ||||
| 			} else { | ||||
| 				if x.CephFS == nil { | ||||
| 					x.CephFS = new(CephFSVolumeSource) | ||||
| 					x.CephFS = new(CephFSPersistentVolumeSource) | ||||
| 				} | ||||
| 				x.CephFS.CodecDecodeSelf(d) | ||||
| 			} | ||||
| @@ -6404,7 +6404,7 @@ func (x *PersistentVolumeSource) codecDecodeSelfFromArray(l int, d *codec1978.De | ||||
| 		} | ||||
| 	} else { | ||||
| 		if x.CephFS == nil { | ||||
| 			x.CephFS = new(CephFSVolumeSource) | ||||
| 			x.CephFS = new(CephFSPersistentVolumeSource) | ||||
| 		} | ||||
| 		x.CephFS.CodecDecodeSelf(d) | ||||
| 	} | ||||
| @@ -8201,7 +8201,7 @@ func (x *PersistentVolumeSpec) codecDecodeSelfFromMap(l int, d *codec1978.Decode | ||||
| 			} | ||||
| 		case "cephfs": | ||||
| 			if x.PersistentVolumeSource.CephFS == nil { | ||||
| 				x.PersistentVolumeSource.CephFS = new(CephFSVolumeSource) | ||||
| 				x.PersistentVolumeSource.CephFS = new(CephFSPersistentVolumeSource) | ||||
| 			} | ||||
| 			if r.TryDecodeAsNil() { | ||||
| 				if x.CephFS != nil { | ||||
| @@ -8209,7 +8209,7 @@ func (x *PersistentVolumeSpec) codecDecodeSelfFromMap(l int, d *codec1978.Decode | ||||
| 				} | ||||
| 			} else { | ||||
| 				if x.CephFS == nil { | ||||
| 					x.CephFS = new(CephFSVolumeSource) | ||||
| 					x.CephFS = new(CephFSPersistentVolumeSource) | ||||
| 				} | ||||
| 				x.CephFS.CodecDecodeSelf(d) | ||||
| 			} | ||||
| @@ -8647,7 +8647,7 @@ func (x *PersistentVolumeSpec) codecDecodeSelfFromArray(l int, d *codec1978.Deco | ||||
| 		x.Cinder.CodecDecodeSelf(d) | ||||
| 	} | ||||
| 	if x.PersistentVolumeSource.CephFS == nil { | ||||
| 		x.PersistentVolumeSource.CephFS = new(CephFSVolumeSource) | ||||
| 		x.PersistentVolumeSource.CephFS = new(CephFSPersistentVolumeSource) | ||||
| 	} | ||||
| 	yyj32++ | ||||
| 	if yyhl32 { | ||||
| @@ -8666,7 +8666,7 @@ func (x *PersistentVolumeSpec) codecDecodeSelfFromArray(l int, d *codec1978.Deco | ||||
| 		} | ||||
| 	} else { | ||||
| 		if x.CephFS == nil { | ||||
| 			x.CephFS = new(CephFSVolumeSource) | ||||
| 			x.CephFS = new(CephFSPersistentVolumeSource) | ||||
| 		} | ||||
| 		x.CephFS.CodecDecodeSelf(d) | ||||
| 	} | ||||
| @@ -13437,6 +13437,725 @@ func (x *CephFSVolumeSource) codecDecodeSelfFromArray(l int, d *codec1978.Decode | ||||
| 	z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| } | ||||
| 
 | ||||
| func (x *SecretReference) CodecEncodeSelf(e *codec1978.Encoder) { | ||||
| 	var h codecSelfer1234 | ||||
| 	z, r := codec1978.GenHelperEncoder(e) | ||||
| 	_, _, _ = h, z, r | ||||
| 	if x == nil { | ||||
| 		r.EncodeNil() | ||||
| 	} else { | ||||
| 		yym1 := z.EncBinary() | ||||
| 		_ = yym1 | ||||
| 		if false { | ||||
| 		} else if z.HasExtensions() && z.EncExt(x) { | ||||
| 		} else { | ||||
| 			yysep2 := !z.EncBinary() | ||||
| 			yy2arr2 := z.EncBasicHandle().StructToArray | ||||
| 			var yyq2 [2]bool | ||||
| 			_, _, _ = yysep2, yyq2, yy2arr2 | ||||
| 			const yyr2 bool = false | ||||
| 			yyq2[0] = x.Name != "" | ||||
| 			yyq2[1] = x.Namespace != "" | ||||
| 			var yynn2 int | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				r.EncodeArrayStart(2) | ||||
| 			} else { | ||||
| 				yynn2 = 0 | ||||
| 				for _, b := range yyq2 { | ||||
| 					if b { | ||||
| 						yynn2++ | ||||
| 					} | ||||
| 				} | ||||
| 				r.EncodeMapStart(yynn2) | ||||
| 				yynn2 = 0 | ||||
| 			} | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				z.EncSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 				if yyq2[0] { | ||||
| 					yym4 := z.EncBinary() | ||||
| 					_ = yym4 | ||||
| 					if false { | ||||
| 					} else { | ||||
| 						r.EncodeString(codecSelferC_UTF81234, string(x.Name)) | ||||
| 					} | ||||
| 				} else { | ||||
| 					r.EncodeString(codecSelferC_UTF81234, "") | ||||
| 				} | ||||
| 			} else { | ||||
| 				if yyq2[0] { | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapKey1234) | ||||
| 					r.EncodeString(codecSelferC_UTF81234, string("name")) | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapValue1234) | ||||
| 					yym5 := z.EncBinary() | ||||
| 					_ = yym5 | ||||
| 					if false { | ||||
| 					} else { | ||||
| 						r.EncodeString(codecSelferC_UTF81234, string(x.Name)) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				z.EncSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 				if yyq2[1] { | ||||
| 					yym7 := z.EncBinary() | ||||
| 					_ = yym7 | ||||
| 					if false { | ||||
| 					} else { | ||||
| 						r.EncodeString(codecSelferC_UTF81234, string(x.Namespace)) | ||||
| 					} | ||||
| 				} else { | ||||
| 					r.EncodeString(codecSelferC_UTF81234, "") | ||||
| 				} | ||||
| 			} else { | ||||
| 				if yyq2[1] { | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapKey1234) | ||||
| 					r.EncodeString(codecSelferC_UTF81234, string("namespace")) | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapValue1234) | ||||
| 					yym8 := z.EncBinary() | ||||
| 					_ = yym8 | ||||
| 					if false { | ||||
| 					} else { | ||||
| 						r.EncodeString(codecSelferC_UTF81234, string(x.Namespace)) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				z.EncSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 			} else { | ||||
| 				z.EncSendContainerState(codecSelfer_containerMapEnd1234) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (x *SecretReference) CodecDecodeSelf(d *codec1978.Decoder) { | ||||
| 	var h codecSelfer1234 | ||||
| 	z, r := codec1978.GenHelperDecoder(d) | ||||
| 	_, _, _ = h, z, r | ||||
| 	yym1 := z.DecBinary() | ||||
| 	_ = yym1 | ||||
| 	if false { | ||||
| 	} else if z.HasExtensions() && z.DecExt(x) { | ||||
| 	} else { | ||||
| 		yyct2 := r.ContainerType() | ||||
| 		if yyct2 == codecSelferValueTypeMap1234 { | ||||
| 			yyl2 := r.ReadMapStart() | ||||
| 			if yyl2 == 0 { | ||||
| 				z.DecSendContainerState(codecSelfer_containerMapEnd1234) | ||||
| 			} else { | ||||
| 				x.codecDecodeSelfFromMap(yyl2, d) | ||||
| 			} | ||||
| 		} else if yyct2 == codecSelferValueTypeArray1234 { | ||||
| 			yyl2 := r.ReadArrayStart() | ||||
| 			if yyl2 == 0 { | ||||
| 				z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 			} else { | ||||
| 				x.codecDecodeSelfFromArray(yyl2, d) | ||||
| 			} | ||||
| 		} else { | ||||
| 			panic(codecSelferOnlyMapOrArrayEncodeToStructErr1234) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (x *SecretReference) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { | ||||
| 	var h codecSelfer1234 | ||||
| 	z, r := codec1978.GenHelperDecoder(d) | ||||
| 	_, _, _ = h, z, r | ||||
| 	var yys3Slc = z.DecScratchBuffer() // default slice to decode into | ||||
| 	_ = yys3Slc | ||||
| 	var yyhl3 bool = l >= 0 | ||||
| 	for yyj3 := 0; ; yyj3++ { | ||||
| 		if yyhl3 { | ||||
| 			if yyj3 >= l { | ||||
| 				break | ||||
| 			} | ||||
| 		} else { | ||||
| 			if r.CheckBreak() { | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 		z.DecSendContainerState(codecSelfer_containerMapKey1234) | ||||
| 		yys3Slc = r.DecodeBytes(yys3Slc, true, true) | ||||
| 		yys3 := string(yys3Slc) | ||||
| 		z.DecSendContainerState(codecSelfer_containerMapValue1234) | ||||
| 		switch yys3 { | ||||
| 		case "name": | ||||
| 			if r.TryDecodeAsNil() { | ||||
| 				x.Name = "" | ||||
| 			} else { | ||||
| 				yyv4 := &x.Name | ||||
| 				yym5 := z.DecBinary() | ||||
| 				_ = yym5 | ||||
| 				if false { | ||||
| 				} else { | ||||
| 					*((*string)(yyv4)) = r.DecodeString() | ||||
| 				} | ||||
| 			} | ||||
| 		case "namespace": | ||||
| 			if r.TryDecodeAsNil() { | ||||
| 				x.Namespace = "" | ||||
| 			} else { | ||||
| 				yyv6 := &x.Namespace | ||||
| 				yym7 := z.DecBinary() | ||||
| 				_ = yym7 | ||||
| 				if false { | ||||
| 				} else { | ||||
| 					*((*string)(yyv6)) = r.DecodeString() | ||||
| 				} | ||||
| 			} | ||||
| 		default: | ||||
| 			z.DecStructFieldNotFound(-1, yys3) | ||||
| 		} // end switch yys3 | ||||
| 	} // end for yyj3 | ||||
| 	z.DecSendContainerState(codecSelfer_containerMapEnd1234) | ||||
| } | ||||
| 
 | ||||
| func (x *SecretReference) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { | ||||
| 	var h codecSelfer1234 | ||||
| 	z, r := codec1978.GenHelperDecoder(d) | ||||
| 	_, _, _ = h, z, r | ||||
| 	var yyj8 int | ||||
| 	var yyb8 bool | ||||
| 	var yyhl8 bool = l >= 0 | ||||
| 	yyj8++ | ||||
| 	if yyhl8 { | ||||
| 		yyb8 = yyj8 > l | ||||
| 	} else { | ||||
| 		yyb8 = r.CheckBreak() | ||||
| 	} | ||||
| 	if yyb8 { | ||||
| 		z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 		return | ||||
| 	} | ||||
| 	z.DecSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 	if r.TryDecodeAsNil() { | ||||
| 		x.Name = "" | ||||
| 	} else { | ||||
| 		yyv9 := &x.Name | ||||
| 		yym10 := z.DecBinary() | ||||
| 		_ = yym10 | ||||
| 		if false { | ||||
| 		} else { | ||||
| 			*((*string)(yyv9)) = r.DecodeString() | ||||
| 		} | ||||
| 	} | ||||
| 	yyj8++ | ||||
| 	if yyhl8 { | ||||
| 		yyb8 = yyj8 > l | ||||
| 	} else { | ||||
| 		yyb8 = r.CheckBreak() | ||||
| 	} | ||||
| 	if yyb8 { | ||||
| 		z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 		return | ||||
| 	} | ||||
| 	z.DecSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 	if r.TryDecodeAsNil() { | ||||
| 		x.Namespace = "" | ||||
| 	} else { | ||||
| 		yyv11 := &x.Namespace | ||||
| 		yym12 := z.DecBinary() | ||||
| 		_ = yym12 | ||||
| 		if false { | ||||
| 		} else { | ||||
| 			*((*string)(yyv11)) = r.DecodeString() | ||||
| 		} | ||||
| 	} | ||||
| 	for { | ||||
| 		yyj8++ | ||||
| 		if yyhl8 { | ||||
| 			yyb8 = yyj8 > l | ||||
| 		} else { | ||||
| 			yyb8 = r.CheckBreak() | ||||
| 		} | ||||
| 		if yyb8 { | ||||
| 			break | ||||
| 		} | ||||
| 		z.DecSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 		z.DecStructFieldNotFound(yyj8-1, "") | ||||
| 	} | ||||
| 	z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| } | ||||
| 
 | ||||
| func (x *CephFSPersistentVolumeSource) CodecEncodeSelf(e *codec1978.Encoder) { | ||||
| 	var h codecSelfer1234 | ||||
| 	z, r := codec1978.GenHelperEncoder(e) | ||||
| 	_, _, _ = h, z, r | ||||
| 	if x == nil { | ||||
| 		r.EncodeNil() | ||||
| 	} else { | ||||
| 		yym1 := z.EncBinary() | ||||
| 		_ = yym1 | ||||
| 		if false { | ||||
| 		} else if z.HasExtensions() && z.EncExt(x) { | ||||
| 		} else { | ||||
| 			yysep2 := !z.EncBinary() | ||||
| 			yy2arr2 := z.EncBasicHandle().StructToArray | ||||
| 			var yyq2 [6]bool | ||||
| 			_, _, _ = yysep2, yyq2, yy2arr2 | ||||
| 			const yyr2 bool = false | ||||
| 			yyq2[1] = x.Path != "" | ||||
| 			yyq2[2] = x.User != "" | ||||
| 			yyq2[3] = x.SecretFile != "" | ||||
| 			yyq2[4] = x.SecretRef != nil | ||||
| 			yyq2[5] = x.ReadOnly != false | ||||
| 			var yynn2 int | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				r.EncodeArrayStart(6) | ||||
| 			} else { | ||||
| 				yynn2 = 1 | ||||
| 				for _, b := range yyq2 { | ||||
| 					if b { | ||||
| 						yynn2++ | ||||
| 					} | ||||
| 				} | ||||
| 				r.EncodeMapStart(yynn2) | ||||
| 				yynn2 = 0 | ||||
| 			} | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				z.EncSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 				if x.Monitors == nil { | ||||
| 					r.EncodeNil() | ||||
| 				} else { | ||||
| 					yym4 := z.EncBinary() | ||||
| 					_ = yym4 | ||||
| 					if false { | ||||
| 					} else { | ||||
| 						z.F.EncSliceStringV(x.Monitors, false, e) | ||||
| 					} | ||||
| 				} | ||||
| 			} else { | ||||
| 				z.EncSendContainerState(codecSelfer_containerMapKey1234) | ||||
| 				r.EncodeString(codecSelferC_UTF81234, string("monitors")) | ||||
| 				z.EncSendContainerState(codecSelfer_containerMapValue1234) | ||||
| 				if x.Monitors == nil { | ||||
| 					r.EncodeNil() | ||||
| 				} else { | ||||
| 					yym5 := z.EncBinary() | ||||
| 					_ = yym5 | ||||
| 					if false { | ||||
| 					} else { | ||||
| 						z.F.EncSliceStringV(x.Monitors, false, e) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				z.EncSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 				if yyq2[1] { | ||||
| 					yym7 := z.EncBinary() | ||||
| 					_ = yym7 | ||||
| 					if false { | ||||
| 					} else { | ||||
| 						r.EncodeString(codecSelferC_UTF81234, string(x.Path)) | ||||
| 					} | ||||
| 				} else { | ||||
| 					r.EncodeString(codecSelferC_UTF81234, "") | ||||
| 				} | ||||
| 			} else { | ||||
| 				if yyq2[1] { | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapKey1234) | ||||
| 					r.EncodeString(codecSelferC_UTF81234, string("path")) | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapValue1234) | ||||
| 					yym8 := z.EncBinary() | ||||
| 					_ = yym8 | ||||
| 					if false { | ||||
| 					} else { | ||||
| 						r.EncodeString(codecSelferC_UTF81234, string(x.Path)) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				z.EncSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 				if yyq2[2] { | ||||
| 					yym10 := z.EncBinary() | ||||
| 					_ = yym10 | ||||
| 					if false { | ||||
| 					} else { | ||||
| 						r.EncodeString(codecSelferC_UTF81234, string(x.User)) | ||||
| 					} | ||||
| 				} else { | ||||
| 					r.EncodeString(codecSelferC_UTF81234, "") | ||||
| 				} | ||||
| 			} else { | ||||
| 				if yyq2[2] { | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapKey1234) | ||||
| 					r.EncodeString(codecSelferC_UTF81234, string("user")) | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapValue1234) | ||||
| 					yym11 := z.EncBinary() | ||||
| 					_ = yym11 | ||||
| 					if false { | ||||
| 					} else { | ||||
| 						r.EncodeString(codecSelferC_UTF81234, string(x.User)) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				z.EncSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 				if yyq2[3] { | ||||
| 					yym13 := z.EncBinary() | ||||
| 					_ = yym13 | ||||
| 					if false { | ||||
| 					} else { | ||||
| 						r.EncodeString(codecSelferC_UTF81234, string(x.SecretFile)) | ||||
| 					} | ||||
| 				} else { | ||||
| 					r.EncodeString(codecSelferC_UTF81234, "") | ||||
| 				} | ||||
| 			} else { | ||||
| 				if yyq2[3] { | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapKey1234) | ||||
| 					r.EncodeString(codecSelferC_UTF81234, string("secretFile")) | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapValue1234) | ||||
| 					yym14 := z.EncBinary() | ||||
| 					_ = yym14 | ||||
| 					if false { | ||||
| 					} else { | ||||
| 						r.EncodeString(codecSelferC_UTF81234, string(x.SecretFile)) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				z.EncSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 				if yyq2[4] { | ||||
| 					if x.SecretRef == nil { | ||||
| 						r.EncodeNil() | ||||
| 					} else { | ||||
| 						x.SecretRef.CodecEncodeSelf(e) | ||||
| 					} | ||||
| 				} else { | ||||
| 					r.EncodeNil() | ||||
| 				} | ||||
| 			} else { | ||||
| 				if yyq2[4] { | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapKey1234) | ||||
| 					r.EncodeString(codecSelferC_UTF81234, string("secretRef")) | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapValue1234) | ||||
| 					if x.SecretRef == nil { | ||||
| 						r.EncodeNil() | ||||
| 					} else { | ||||
| 						x.SecretRef.CodecEncodeSelf(e) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				z.EncSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 				if yyq2[5] { | ||||
| 					yym19 := z.EncBinary() | ||||
| 					_ = yym19 | ||||
| 					if false { | ||||
| 					} else { | ||||
| 						r.EncodeBool(bool(x.ReadOnly)) | ||||
| 					} | ||||
| 				} else { | ||||
| 					r.EncodeBool(false) | ||||
| 				} | ||||
| 			} else { | ||||
| 				if yyq2[5] { | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapKey1234) | ||||
| 					r.EncodeString(codecSelferC_UTF81234, string("readOnly")) | ||||
| 					z.EncSendContainerState(codecSelfer_containerMapValue1234) | ||||
| 					yym20 := z.EncBinary() | ||||
| 					_ = yym20 | ||||
| 					if false { | ||||
| 					} else { | ||||
| 						r.EncodeBool(bool(x.ReadOnly)) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			if yyr2 || yy2arr2 { | ||||
| 				z.EncSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 			} else { | ||||
| 				z.EncSendContainerState(codecSelfer_containerMapEnd1234) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (x *CephFSPersistentVolumeSource) CodecDecodeSelf(d *codec1978.Decoder) { | ||||
| 	var h codecSelfer1234 | ||||
| 	z, r := codec1978.GenHelperDecoder(d) | ||||
| 	_, _, _ = h, z, r | ||||
| 	yym1 := z.DecBinary() | ||||
| 	_ = yym1 | ||||
| 	if false { | ||||
| 	} else if z.HasExtensions() && z.DecExt(x) { | ||||
| 	} else { | ||||
| 		yyct2 := r.ContainerType() | ||||
| 		if yyct2 == codecSelferValueTypeMap1234 { | ||||
| 			yyl2 := r.ReadMapStart() | ||||
| 			if yyl2 == 0 { | ||||
| 				z.DecSendContainerState(codecSelfer_containerMapEnd1234) | ||||
| 			} else { | ||||
| 				x.codecDecodeSelfFromMap(yyl2, d) | ||||
| 			} | ||||
| 		} else if yyct2 == codecSelferValueTypeArray1234 { | ||||
| 			yyl2 := r.ReadArrayStart() | ||||
| 			if yyl2 == 0 { | ||||
| 				z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 			} else { | ||||
| 				x.codecDecodeSelfFromArray(yyl2, d) | ||||
| 			} | ||||
| 		} else { | ||||
| 			panic(codecSelferOnlyMapOrArrayEncodeToStructErr1234) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (x *CephFSPersistentVolumeSource) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { | ||||
| 	var h codecSelfer1234 | ||||
| 	z, r := codec1978.GenHelperDecoder(d) | ||||
| 	_, _, _ = h, z, r | ||||
| 	var yys3Slc = z.DecScratchBuffer() // default slice to decode into | ||||
| 	_ = yys3Slc | ||||
| 	var yyhl3 bool = l >= 0 | ||||
| 	for yyj3 := 0; ; yyj3++ { | ||||
| 		if yyhl3 { | ||||
| 			if yyj3 >= l { | ||||
| 				break | ||||
| 			} | ||||
| 		} else { | ||||
| 			if r.CheckBreak() { | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 		z.DecSendContainerState(codecSelfer_containerMapKey1234) | ||||
| 		yys3Slc = r.DecodeBytes(yys3Slc, true, true) | ||||
| 		yys3 := string(yys3Slc) | ||||
| 		z.DecSendContainerState(codecSelfer_containerMapValue1234) | ||||
| 		switch yys3 { | ||||
| 		case "monitors": | ||||
| 			if r.TryDecodeAsNil() { | ||||
| 				x.Monitors = nil | ||||
| 			} else { | ||||
| 				yyv4 := &x.Monitors | ||||
| 				yym5 := z.DecBinary() | ||||
| 				_ = yym5 | ||||
| 				if false { | ||||
| 				} else { | ||||
| 					z.F.DecSliceStringX(yyv4, false, d) | ||||
| 				} | ||||
| 			} | ||||
| 		case "path": | ||||
| 			if r.TryDecodeAsNil() { | ||||
| 				x.Path = "" | ||||
| 			} else { | ||||
| 				yyv6 := &x.Path | ||||
| 				yym7 := z.DecBinary() | ||||
| 				_ = yym7 | ||||
| 				if false { | ||||
| 				} else { | ||||
| 					*((*string)(yyv6)) = r.DecodeString() | ||||
| 				} | ||||
| 			} | ||||
| 		case "user": | ||||
| 			if r.TryDecodeAsNil() { | ||||
| 				x.User = "" | ||||
| 			} else { | ||||
| 				yyv8 := &x.User | ||||
| 				yym9 := z.DecBinary() | ||||
| 				_ = yym9 | ||||
| 				if false { | ||||
| 				} else { | ||||
| 					*((*string)(yyv8)) = r.DecodeString() | ||||
| 				} | ||||
| 			} | ||||
| 		case "secretFile": | ||||
| 			if r.TryDecodeAsNil() { | ||||
| 				x.SecretFile = "" | ||||
| 			} else { | ||||
| 				yyv10 := &x.SecretFile | ||||
| 				yym11 := z.DecBinary() | ||||
| 				_ = yym11 | ||||
| 				if false { | ||||
| 				} else { | ||||
| 					*((*string)(yyv10)) = r.DecodeString() | ||||
| 				} | ||||
| 			} | ||||
| 		case "secretRef": | ||||
| 			if r.TryDecodeAsNil() { | ||||
| 				if x.SecretRef != nil { | ||||
| 					x.SecretRef = nil | ||||
| 				} | ||||
| 			} else { | ||||
| 				if x.SecretRef == nil { | ||||
| 					x.SecretRef = new(SecretReference) | ||||
| 				} | ||||
| 				x.SecretRef.CodecDecodeSelf(d) | ||||
| 			} | ||||
| 		case "readOnly": | ||||
| 			if r.TryDecodeAsNil() { | ||||
| 				x.ReadOnly = false | ||||
| 			} else { | ||||
| 				yyv13 := &x.ReadOnly | ||||
| 				yym14 := z.DecBinary() | ||||
| 				_ = yym14 | ||||
| 				if false { | ||||
| 				} else { | ||||
| 					*((*bool)(yyv13)) = r.DecodeBool() | ||||
| 				} | ||||
| 			} | ||||
| 		default: | ||||
| 			z.DecStructFieldNotFound(-1, yys3) | ||||
| 		} // end switch yys3 | ||||
| 	} // end for yyj3 | ||||
| 	z.DecSendContainerState(codecSelfer_containerMapEnd1234) | ||||
| } | ||||
| 
 | ||||
| func (x *CephFSPersistentVolumeSource) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { | ||||
| 	var h codecSelfer1234 | ||||
| 	z, r := codec1978.GenHelperDecoder(d) | ||||
| 	_, _, _ = h, z, r | ||||
| 	var yyj15 int | ||||
| 	var yyb15 bool | ||||
| 	var yyhl15 bool = l >= 0 | ||||
| 	yyj15++ | ||||
| 	if yyhl15 { | ||||
| 		yyb15 = yyj15 > l | ||||
| 	} else { | ||||
| 		yyb15 = r.CheckBreak() | ||||
| 	} | ||||
| 	if yyb15 { | ||||
| 		z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 		return | ||||
| 	} | ||||
| 	z.DecSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 	if r.TryDecodeAsNil() { | ||||
| 		x.Monitors = nil | ||||
| 	} else { | ||||
| 		yyv16 := &x.Monitors | ||||
| 		yym17 := z.DecBinary() | ||||
| 		_ = yym17 | ||||
| 		if false { | ||||
| 		} else { | ||||
| 			z.F.DecSliceStringX(yyv16, false, d) | ||||
| 		} | ||||
| 	} | ||||
| 	yyj15++ | ||||
| 	if yyhl15 { | ||||
| 		yyb15 = yyj15 > l | ||||
| 	} else { | ||||
| 		yyb15 = r.CheckBreak() | ||||
| 	} | ||||
| 	if yyb15 { | ||||
| 		z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 		return | ||||
| 	} | ||||
| 	z.DecSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 	if r.TryDecodeAsNil() { | ||||
| 		x.Path = "" | ||||
| 	} else { | ||||
| 		yyv18 := &x.Path | ||||
| 		yym19 := z.DecBinary() | ||||
| 		_ = yym19 | ||||
| 		if false { | ||||
| 		} else { | ||||
| 			*((*string)(yyv18)) = r.DecodeString() | ||||
| 		} | ||||
| 	} | ||||
| 	yyj15++ | ||||
| 	if yyhl15 { | ||||
| 		yyb15 = yyj15 > l | ||||
| 	} else { | ||||
| 		yyb15 = r.CheckBreak() | ||||
| 	} | ||||
| 	if yyb15 { | ||||
| 		z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 		return | ||||
| 	} | ||||
| 	z.DecSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 	if r.TryDecodeAsNil() { | ||||
| 		x.User = "" | ||||
| 	} else { | ||||
| 		yyv20 := &x.User | ||||
| 		yym21 := z.DecBinary() | ||||
| 		_ = yym21 | ||||
| 		if false { | ||||
| 		} else { | ||||
| 			*((*string)(yyv20)) = r.DecodeString() | ||||
| 		} | ||||
| 	} | ||||
| 	yyj15++ | ||||
| 	if yyhl15 { | ||||
| 		yyb15 = yyj15 > l | ||||
| 	} else { | ||||
| 		yyb15 = r.CheckBreak() | ||||
| 	} | ||||
| 	if yyb15 { | ||||
| 		z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 		return | ||||
| 	} | ||||
| 	z.DecSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 	if r.TryDecodeAsNil() { | ||||
| 		x.SecretFile = "" | ||||
| 	} else { | ||||
| 		yyv22 := &x.SecretFile | ||||
| 		yym23 := z.DecBinary() | ||||
| 		_ = yym23 | ||||
| 		if false { | ||||
| 		} else { | ||||
| 			*((*string)(yyv22)) = r.DecodeString() | ||||
| 		} | ||||
| 	} | ||||
| 	yyj15++ | ||||
| 	if yyhl15 { | ||||
| 		yyb15 = yyj15 > l | ||||
| 	} else { | ||||
| 		yyb15 = r.CheckBreak() | ||||
| 	} | ||||
| 	if yyb15 { | ||||
| 		z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 		return | ||||
| 	} | ||||
| 	z.DecSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 	if r.TryDecodeAsNil() { | ||||
| 		if x.SecretRef != nil { | ||||
| 			x.SecretRef = nil | ||||
| 		} | ||||
| 	} else { | ||||
| 		if x.SecretRef == nil { | ||||
| 			x.SecretRef = new(SecretReference) | ||||
| 		} | ||||
| 		x.SecretRef.CodecDecodeSelf(d) | ||||
| 	} | ||||
| 	yyj15++ | ||||
| 	if yyhl15 { | ||||
| 		yyb15 = yyj15 > l | ||||
| 	} else { | ||||
| 		yyb15 = r.CheckBreak() | ||||
| 	} | ||||
| 	if yyb15 { | ||||
| 		z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| 		return | ||||
| 	} | ||||
| 	z.DecSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 	if r.TryDecodeAsNil() { | ||||
| 		x.ReadOnly = false | ||||
| 	} else { | ||||
| 		yyv25 := &x.ReadOnly | ||||
| 		yym26 := z.DecBinary() | ||||
| 		_ = yym26 | ||||
| 		if false { | ||||
| 		} else { | ||||
| 			*((*bool)(yyv25)) = r.DecodeBool() | ||||
| 		} | ||||
| 	} | ||||
| 	for { | ||||
| 		yyj15++ | ||||
| 		if yyhl15 { | ||||
| 			yyb15 = yyj15 > l | ||||
| 		} else { | ||||
| 			yyb15 = r.CheckBreak() | ||||
| 		} | ||||
| 		if yyb15 { | ||||
| 			break | ||||
| 		} | ||||
| 		z.DecSendContainerState(codecSelfer_containerArrayElem1234) | ||||
| 		z.DecStructFieldNotFound(yyj15-1, "") | ||||
| 	} | ||||
| 	z.DecSendContainerState(codecSelfer_containerArrayEnd1234) | ||||
| } | ||||
| 
 | ||||
| func (x *FlockerVolumeSource) CodecEncodeSelf(e *codec1978.Encoder) { | ||||
| 	var h codecSelfer1234 | ||||
| 	z, r := codec1978.GenHelperEncoder(e) | ||||
|   | ||||
| @@ -409,7 +409,7 @@ type PersistentVolumeSource struct { | ||||
| 	Cinder *CinderVolumeSource `json:"cinder,omitempty" protobuf:"bytes,8,opt,name=cinder"` | ||||
| 	// CephFS represents a Ceph FS mount on the host that shares a pod's lifetime | ||||
| 	// +optional | ||||
| 	CephFS *CephFSVolumeSource `json:"cephfs,omitempty" protobuf:"bytes,9,opt,name=cephfs"` | ||||
| 	CephFS *CephFSPersistentVolumeSource `json:"cephfs,omitempty" protobuf:"bytes,9,opt,name=cephfs"` | ||||
| 	// FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod. | ||||
| 	// +optional | ||||
| 	FC *FCVolumeSource `json:"fc,omitempty" protobuf:"bytes,10,opt,name=fc"` | ||||
| @@ -848,6 +848,45 @@ type CephFSVolumeSource struct { | ||||
| 	ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,6,opt,name=readOnly"` | ||||
| } | ||||
|  | ||||
| // SecretReference represents a Secret Reference. It has enough information to retrieve secret | ||||
| // in any namespace | ||||
| type SecretReference struct { | ||||
| 	// Name is unique within a namespace to reference a secret resource. | ||||
| 	// +optional | ||||
| 	Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"` | ||||
| 	// Namespace defines the space within which the secret name must be unique. | ||||
| 	// +optional | ||||
| 	Namespace string `json:"namespace,omitempty" protobuf:"bytes,2,opt,name=namespace"` | ||||
| } | ||||
|  | ||||
| // Represents a Ceph Filesystem mount that lasts the lifetime of a pod | ||||
| // Cephfs volumes do not support ownership management or SELinux relabeling. | ||||
| type CephFSPersistentVolumeSource struct { | ||||
| 	// Required: Monitors is a collection of Ceph monitors | ||||
| 	// More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it | ||||
| 	Monitors []string `json:"monitors" protobuf:"bytes,1,rep,name=monitors"` | ||||
| 	// Optional: Used as the mounted root, rather than the full Ceph tree, default is / | ||||
| 	// +optional | ||||
| 	Path string `json:"path,omitempty" protobuf:"bytes,2,opt,name=path"` | ||||
| 	// Optional: User is the rados user name, default is admin | ||||
| 	// More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it | ||||
| 	// +optional | ||||
| 	User string `json:"user,omitempty" protobuf:"bytes,3,opt,name=user"` | ||||
| 	// Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret | ||||
| 	// More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it | ||||
| 	// +optional | ||||
| 	SecretFile string `json:"secretFile,omitempty" protobuf:"bytes,4,opt,name=secretFile"` | ||||
| 	// Optional: SecretRef is reference to the authentication secret for User, default is empty. | ||||
| 	// More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it | ||||
| 	// +optional | ||||
| 	SecretRef *SecretReference `json:"secretRef,omitempty" protobuf:"bytes,5,opt,name=secretRef"` | ||||
| 	// Optional: Defaults to false (read/write). ReadOnly here will force | ||||
| 	// the ReadOnly setting in VolumeMounts. | ||||
| 	// More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it | ||||
| 	// +optional | ||||
| 	ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,6,opt,name=readOnly"` | ||||
| } | ||||
|  | ||||
| // Represents a Flocker volume mounted by the Flocker agent. | ||||
| // One and only one of datasetName and datasetUUID should be set. | ||||
| // Flocker volumes do not support ownership management or SELinux relabeling. | ||||
|   | ||||
| @@ -126,6 +126,20 @@ func (Capabilities) SwaggerDoc() map[string]string { | ||||
| 	return map_Capabilities | ||||
| } | ||||
| 
 | ||||
| var map_CephFSPersistentVolumeSource = map[string]string{ | ||||
| 	"":           "Represents a Ceph Filesystem mount that lasts the lifetime of a pod Cephfs volumes do not support ownership management or SELinux relabeling.", | ||||
| 	"monitors":   "Required: Monitors is a collection of Ceph monitors More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", | ||||
| 	"path":       "Optional: Used as the mounted root, rather than the full Ceph tree, default is /", | ||||
| 	"user":       "Optional: User is the rados user name, default is admin More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", | ||||
| 	"secretFile": "Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", | ||||
| 	"secretRef":  "Optional: SecretRef is reference to the authentication secret for User, default is empty. More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", | ||||
| 	"readOnly":   "Optional: Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", | ||||
| } | ||||
| 
 | ||||
| func (CephFSPersistentVolumeSource) SwaggerDoc() map[string]string { | ||||
| 	return map_CephFSPersistentVolumeSource | ||||
| } | ||||
| 
 | ||||
| var map_CephFSVolumeSource = map[string]string{ | ||||
| 	"":           "Represents a Ceph Filesystem mount that lasts the lifetime of a pod Cephfs volumes do not support ownership management or SELinux relabeling.", | ||||
| 	"monitors":   "Required: Monitors is a collection of Ceph monitors More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", | ||||
| @@ -1764,6 +1778,16 @@ func (SecretProjection) SwaggerDoc() map[string]string { | ||||
| 	return map_SecretProjection | ||||
| } | ||||
| 
 | ||||
| var map_SecretReference = map[string]string{ | ||||
| 	"":          "SecretReference represents a Secret Reference. It has enough information to retrieve secret in any namespace", | ||||
| 	"name":      "Name is unique within a namespace to reference a secret resource.", | ||||
| 	"namespace": "Namespace defines the space within which the secret name must be unique.", | ||||
| } | ||||
| 
 | ||||
| func (SecretReference) SwaggerDoc() map[string]string { | ||||
| 	return map_SecretReference | ||||
| } | ||||
| 
 | ||||
| var map_SecretVolumeSource = map[string]string{ | ||||
| 	"":            "Adapts a Secret into a volume.\n\nThe contents of the target Secret's Data field will be presented in a volume as files using the keys in the Data field as the file names. Secret volumes support ownership management and SELinux relabeling.", | ||||
| 	"secretName":  "Name of the secret in the pod's namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret", | ||||
|   | ||||
| @@ -74,6 +74,10 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { | ||||
| 			in.(*Capabilities).DeepCopyInto(out.(*Capabilities)) | ||||
| 			return nil | ||||
| 		}, InType: reflect.TypeOf(&Capabilities{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { | ||||
| 			in.(*CephFSPersistentVolumeSource).DeepCopyInto(out.(*CephFSPersistentVolumeSource)) | ||||
| 			return nil | ||||
| 		}, InType: reflect.TypeOf(&CephFSPersistentVolumeSource{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { | ||||
| 			in.(*CephFSVolumeSource).DeepCopyInto(out.(*CephFSVolumeSource)) | ||||
| 			return nil | ||||
| @@ -638,6 +642,10 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { | ||||
| 			in.(*SecretProjection).DeepCopyInto(out.(*SecretProjection)) | ||||
| 			return nil | ||||
| 		}, InType: reflect.TypeOf(&SecretProjection{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { | ||||
| 			in.(*SecretReference).DeepCopyInto(out.(*SecretReference)) | ||||
| 			return nil | ||||
| 		}, InType: reflect.TypeOf(&SecretReference{})}, | ||||
| 		conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error { | ||||
| 			in.(*SecretVolumeSource).DeepCopyInto(out.(*SecretVolumeSource)) | ||||
| 			return nil | ||||
| @@ -978,6 +986,36 @@ func (in *Capabilities) DeepCopy() *Capabilities { | ||||
| 	return out | ||||
| } | ||||
| 
 | ||||
| // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. | ||||
| func (in *CephFSPersistentVolumeSource) DeepCopyInto(out *CephFSPersistentVolumeSource) { | ||||
| 	*out = *in | ||||
| 	if in.Monitors != nil { | ||||
| 		in, out := &in.Monitors, &out.Monitors | ||||
| 		*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 CephFSPersistentVolumeSource. | ||||
| func (in *CephFSPersistentVolumeSource) DeepCopy() *CephFSPersistentVolumeSource { | ||||
| 	if in == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	out := new(CephFSPersistentVolumeSource) | ||||
| 	in.DeepCopyInto(out) | ||||
| 	return out | ||||
| } | ||||
| 
 | ||||
| // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. | ||||
| func (in *CephFSVolumeSource) DeepCopyInto(out *CephFSVolumeSource) { | ||||
| 	*out = *in | ||||
| @@ -3649,7 +3687,7 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) { | ||||
| 		if *in == nil { | ||||
| 			*out = nil | ||||
| 		} else { | ||||
| 			*out = new(CephFSVolumeSource) | ||||
| 			*out = new(CephFSPersistentVolumeSource) | ||||
| 			(*in).DeepCopyInto(*out) | ||||
| 		} | ||||
| 	} | ||||
| @@ -5265,6 +5303,22 @@ func (in *SecretProjection) DeepCopy() *SecretProjection { | ||||
| 	return out | ||||
| } | ||||
| 
 | ||||
| // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. | ||||
| func (in *SecretReference) DeepCopyInto(out *SecretReference) { | ||||
| 	*out = *in | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretReference. | ||||
| func (in *SecretReference) DeepCopy() *SecretReference { | ||||
| 	if in == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	out := new(SecretReference) | ||||
| 	in.DeepCopyInto(out) | ||||
| 	return out | ||||
| } | ||||
| 
 | ||||
| // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. | ||||
| func (in *SecretVolumeSource) DeepCopyInto(out *SecretVolumeSource) { | ||||
| 	*out = *in | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Kubernetes Submit Queue
					Kubernetes Submit Queue