conversion.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. /*
  2. Copyright 2015 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package v1
  14. import (
  15. "fmt"
  16. "reflect"
  17. v1 "k8s.io/api/core/v1"
  18. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  19. "k8s.io/apimachinery/pkg/conversion"
  20. "k8s.io/apimachinery/pkg/runtime"
  21. "k8s.io/apimachinery/pkg/util/validation/field"
  22. "k8s.io/kubernetes/pkg/apis/apps"
  23. "k8s.io/kubernetes/pkg/apis/core"
  24. )
  25. func addConversionFuncs(scheme *runtime.Scheme) error {
  26. // Add field conversion funcs.
  27. err := scheme.AddFieldLabelConversionFunc(SchemeGroupVersion.WithKind("Pod"),
  28. func(label, value string) (string, string, error) {
  29. switch label {
  30. case "metadata.name",
  31. "metadata.namespace",
  32. "spec.nodeName",
  33. "spec.restartPolicy",
  34. "spec.schedulerName",
  35. "spec.serviceAccountName",
  36. "status.phase",
  37. "status.podIP",
  38. "status.podIPs",
  39. "status.nominatedNodeName":
  40. return label, value, nil
  41. // This is for backwards compatibility with old v1 clients which send spec.host
  42. case "spec.host":
  43. return "spec.nodeName", value, nil
  44. default:
  45. return "", "", fmt.Errorf("field label not supported: %s", label)
  46. }
  47. },
  48. )
  49. if err != nil {
  50. return err
  51. }
  52. err = scheme.AddFieldLabelConversionFunc(SchemeGroupVersion.WithKind("Node"),
  53. func(label, value string) (string, string, error) {
  54. switch label {
  55. case "metadata.name":
  56. return label, value, nil
  57. case "spec.unschedulable":
  58. return label, value, nil
  59. default:
  60. return "", "", fmt.Errorf("field label not supported: %s", label)
  61. }
  62. },
  63. )
  64. if err != nil {
  65. return err
  66. }
  67. err = scheme.AddFieldLabelConversionFunc(SchemeGroupVersion.WithKind("ReplicationController"),
  68. func(label, value string) (string, string, error) {
  69. switch label {
  70. case "metadata.name",
  71. "metadata.namespace",
  72. "status.replicas":
  73. return label, value, nil
  74. default:
  75. return "", "", fmt.Errorf("field label not supported: %s", label)
  76. }
  77. })
  78. if err != nil {
  79. return err
  80. }
  81. if err := AddFieldLabelConversionsForEvent(scheme); err != nil {
  82. return err
  83. }
  84. if err := AddFieldLabelConversionsForNamespace(scheme); err != nil {
  85. return err
  86. }
  87. if err := AddFieldLabelConversionsForSecret(scheme); err != nil {
  88. return err
  89. }
  90. return nil
  91. }
  92. func Convert_v1_ReplicationController_To_apps_ReplicaSet(in *v1.ReplicationController, out *apps.ReplicaSet, s conversion.Scope) error {
  93. out.ObjectMeta = in.ObjectMeta
  94. if err := Convert_v1_ReplicationControllerSpec_To_apps_ReplicaSetSpec(&in.Spec, &out.Spec, s); err != nil {
  95. return err
  96. }
  97. if err := Convert_v1_ReplicationControllerStatus_To_apps_ReplicaSetStatus(&in.Status, &out.Status, s); err != nil {
  98. return err
  99. }
  100. return nil
  101. }
  102. func Convert_v1_ReplicationControllerSpec_To_apps_ReplicaSetSpec(in *v1.ReplicationControllerSpec, out *apps.ReplicaSetSpec, s conversion.Scope) error {
  103. out.Replicas = *in.Replicas
  104. out.MinReadySeconds = in.MinReadySeconds
  105. if in.Selector != nil {
  106. out.Selector = new(metav1.LabelSelector)
  107. metav1.Convert_Map_string_To_string_To_v1_LabelSelector(&in.Selector, out.Selector, s)
  108. }
  109. if in.Template != nil {
  110. if err := Convert_v1_PodTemplateSpec_To_core_PodTemplateSpec(in.Template, &out.Template, s); err != nil {
  111. return err
  112. }
  113. }
  114. return nil
  115. }
  116. func Convert_v1_ReplicationControllerStatus_To_apps_ReplicaSetStatus(in *v1.ReplicationControllerStatus, out *apps.ReplicaSetStatus, s conversion.Scope) error {
  117. out.Replicas = in.Replicas
  118. out.FullyLabeledReplicas = in.FullyLabeledReplicas
  119. out.ReadyReplicas = in.ReadyReplicas
  120. out.AvailableReplicas = in.AvailableReplicas
  121. out.ObservedGeneration = in.ObservedGeneration
  122. for _, cond := range in.Conditions {
  123. out.Conditions = append(out.Conditions, apps.ReplicaSetCondition{
  124. Type: apps.ReplicaSetConditionType(cond.Type),
  125. Status: core.ConditionStatus(cond.Status),
  126. LastTransitionTime: cond.LastTransitionTime,
  127. Reason: cond.Reason,
  128. Message: cond.Message,
  129. })
  130. }
  131. return nil
  132. }
  133. func Convert_apps_ReplicaSet_To_v1_ReplicationController(in *apps.ReplicaSet, out *v1.ReplicationController, s conversion.Scope) error {
  134. out.ObjectMeta = in.ObjectMeta
  135. if err := Convert_apps_ReplicaSetSpec_To_v1_ReplicationControllerSpec(&in.Spec, &out.Spec, s); err != nil {
  136. fieldErr, ok := err.(*field.Error)
  137. if !ok {
  138. return err
  139. }
  140. if out.Annotations == nil {
  141. out.Annotations = make(map[string]string)
  142. }
  143. out.Annotations[v1.NonConvertibleAnnotationPrefix+"/"+fieldErr.Field] = reflect.ValueOf(fieldErr.BadValue).String()
  144. }
  145. if err := Convert_apps_ReplicaSetStatus_To_v1_ReplicationControllerStatus(&in.Status, &out.Status, s); err != nil {
  146. return err
  147. }
  148. return nil
  149. }
  150. func Convert_apps_ReplicaSetSpec_To_v1_ReplicationControllerSpec(in *apps.ReplicaSetSpec, out *v1.ReplicationControllerSpec, s conversion.Scope) error {
  151. out.Replicas = new(int32)
  152. *out.Replicas = in.Replicas
  153. out.MinReadySeconds = in.MinReadySeconds
  154. var invalidErr error
  155. if in.Selector != nil {
  156. invalidErr = metav1.Convert_v1_LabelSelector_To_Map_string_To_string(in.Selector, &out.Selector, s)
  157. }
  158. out.Template = new(v1.PodTemplateSpec)
  159. if err := Convert_core_PodTemplateSpec_To_v1_PodTemplateSpec(&in.Template, out.Template, s); err != nil {
  160. return err
  161. }
  162. return invalidErr
  163. }
  164. func Convert_apps_ReplicaSetStatus_To_v1_ReplicationControllerStatus(in *apps.ReplicaSetStatus, out *v1.ReplicationControllerStatus, s conversion.Scope) error {
  165. out.Replicas = in.Replicas
  166. out.FullyLabeledReplicas = in.FullyLabeledReplicas
  167. out.ReadyReplicas = in.ReadyReplicas
  168. out.AvailableReplicas = in.AvailableReplicas
  169. out.ObservedGeneration = in.ObservedGeneration
  170. for _, cond := range in.Conditions {
  171. out.Conditions = append(out.Conditions, v1.ReplicationControllerCondition{
  172. Type: v1.ReplicationControllerConditionType(cond.Type),
  173. Status: v1.ConditionStatus(cond.Status),
  174. LastTransitionTime: cond.LastTransitionTime,
  175. Reason: cond.Reason,
  176. Message: cond.Message,
  177. })
  178. }
  179. return nil
  180. }
  181. func Convert_core_ReplicationControllerSpec_To_v1_ReplicationControllerSpec(in *core.ReplicationControllerSpec, out *v1.ReplicationControllerSpec, s conversion.Scope) error {
  182. out.Replicas = &in.Replicas
  183. out.MinReadySeconds = in.MinReadySeconds
  184. out.Selector = in.Selector
  185. if in.Template != nil {
  186. out.Template = new(v1.PodTemplateSpec)
  187. if err := Convert_core_PodTemplateSpec_To_v1_PodTemplateSpec(in.Template, out.Template, s); err != nil {
  188. return err
  189. }
  190. } else {
  191. out.Template = nil
  192. }
  193. return nil
  194. }
  195. func Convert_v1_ReplicationControllerSpec_To_core_ReplicationControllerSpec(in *v1.ReplicationControllerSpec, out *core.ReplicationControllerSpec, s conversion.Scope) error {
  196. if in.Replicas != nil {
  197. out.Replicas = *in.Replicas
  198. }
  199. out.MinReadySeconds = in.MinReadySeconds
  200. out.Selector = in.Selector
  201. if in.Template != nil {
  202. out.Template = new(core.PodTemplateSpec)
  203. if err := Convert_v1_PodTemplateSpec_To_core_PodTemplateSpec(in.Template, out.Template, s); err != nil {
  204. return err
  205. }
  206. } else {
  207. out.Template = nil
  208. }
  209. return nil
  210. }
  211. func Convert_core_PodTemplateSpec_To_v1_PodTemplateSpec(in *core.PodTemplateSpec, out *v1.PodTemplateSpec, s conversion.Scope) error {
  212. if err := autoConvert_core_PodTemplateSpec_To_v1_PodTemplateSpec(in, out, s); err != nil {
  213. return err
  214. }
  215. // drop init container annotations so they don't take effect on legacy kubelets.
  216. // remove this once the oldest supported kubelet no longer honors the annotations over the field.
  217. out.Annotations = dropInitContainerAnnotations(out.Annotations)
  218. return nil
  219. }
  220. func Convert_v1_PodTemplateSpec_To_core_PodTemplateSpec(in *v1.PodTemplateSpec, out *core.PodTemplateSpec, s conversion.Scope) error {
  221. if err := autoConvert_v1_PodTemplateSpec_To_core_PodTemplateSpec(in, out, s); err != nil {
  222. return err
  223. }
  224. // drop init container annotations so they don't show up as differences when receiving requests from old clients
  225. out.Annotations = dropInitContainerAnnotations(out.Annotations)
  226. return nil
  227. }
  228. func Convert_v1_PodStatus_To_core_PodStatus(in *v1.PodStatus, out *core.PodStatus, s conversion.Scope) error {
  229. if err := autoConvert_v1_PodStatus_To_core_PodStatus(in, out, s); err != nil {
  230. return err
  231. }
  232. // If both fields (v1.PodIPs and v1.PodIP) are provided, then test v1.PodIP == v1.PodIPs[0]
  233. if (len(in.PodIP) > 0 && len(in.PodIPs) > 0) && (in.PodIP != in.PodIPs[0].IP) {
  234. return fmt.Errorf("conversion Error: v1.PodIP(%v) != v1.PodIPs[0](%v)", in.PodIP, in.PodIPs[0].IP)
  235. }
  236. // at the this point, autoConvert copied v1.PodIPs -> core.PodIPs
  237. // if v1.PodIPs was empty but v1.PodIP is not, then set core.PodIPs[0] with v1.PodIP
  238. if len(in.PodIP) > 0 && len(in.PodIPs) == 0 {
  239. out.PodIPs = []core.PodIP{
  240. {
  241. IP: in.PodIP,
  242. },
  243. }
  244. }
  245. return nil
  246. }
  247. func Convert_core_PodStatus_To_v1_PodStatus(in *core.PodStatus, out *v1.PodStatus, s conversion.Scope) error {
  248. if err := autoConvert_core_PodStatus_To_v1_PodStatus(in, out, s); err != nil {
  249. return err
  250. }
  251. // at the this point autoConvert copied core.PodIPs -> v1.PodIPs
  252. // v1.PodIP (singular value field, which does not exist in core) needs to
  253. // be set with core.PodIPs[0]
  254. if len(in.PodIPs) > 0 {
  255. out.PodIP = in.PodIPs[0].IP
  256. }
  257. return nil
  258. }
  259. // The following two v1.PodSpec conversions are done here to support v1.ServiceAccount
  260. // as an alias for ServiceAccountName.
  261. func Convert_core_PodSpec_To_v1_PodSpec(in *core.PodSpec, out *v1.PodSpec, s conversion.Scope) error {
  262. if err := autoConvert_core_PodSpec_To_v1_PodSpec(in, out, s); err != nil {
  263. return err
  264. }
  265. // DeprecatedServiceAccount is an alias for ServiceAccountName.
  266. out.DeprecatedServiceAccount = in.ServiceAccountName
  267. if in.SecurityContext != nil {
  268. // the host namespace fields have to be handled here for backward compatibility
  269. // with v1.0.0
  270. out.HostPID = in.SecurityContext.HostPID
  271. out.HostNetwork = in.SecurityContext.HostNetwork
  272. out.HostIPC = in.SecurityContext.HostIPC
  273. out.ShareProcessNamespace = in.SecurityContext.ShareProcessNamespace
  274. }
  275. return nil
  276. }
  277. func Convert_core_NodeSpec_To_v1_NodeSpec(in *core.NodeSpec, out *v1.NodeSpec, s conversion.Scope) error {
  278. if err := autoConvert_core_NodeSpec_To_v1_NodeSpec(in, out, s); err != nil {
  279. return err
  280. }
  281. // at the this point autoConvert copied core.PodCIDRs -> v1.PodCIDRs
  282. // v1.PodCIDR (singular value field, which does not exist in core) needs to
  283. // be set with core.PodCIDRs[0]
  284. if len(in.PodCIDRs) > 0 {
  285. out.PodCIDR = in.PodCIDRs[0]
  286. }
  287. return nil
  288. }
  289. func Convert_v1_NodeSpec_To_core_NodeSpec(in *v1.NodeSpec, out *core.NodeSpec, s conversion.Scope) error {
  290. if err := autoConvert_v1_NodeSpec_To_core_NodeSpec(in, out, s); err != nil {
  291. return err
  292. }
  293. // If both fields (v1.PodCIDRs and v1.PodCIDR) are provided, then test v1.PodCIDR == v1.PodCIDRs[0]
  294. if (len(in.PodCIDR) > 0 && len(in.PodCIDRs) > 0) && (in.PodCIDR != in.PodCIDRs[0]) {
  295. return fmt.Errorf("conversion Error: v1.PodCIDR(%v) != v1.CIDRs[0](%v)", in.PodCIDR, in.PodCIDRs[0])
  296. }
  297. // at the this point, autoConvert copied v1.PodCIDRs -> core.PodCIDRs
  298. // if v1.PodCIDRs was empty but v1.PodCIDR is not, then set core.PodCIDRs[0] with v1.PodCIDR
  299. if len(in.PodCIDR) > 0 && len(in.PodCIDRs) == 0 {
  300. out.PodCIDRs = []string{in.PodCIDR}
  301. }
  302. return nil
  303. }
  304. func Convert_v1_PodSpec_To_core_PodSpec(in *v1.PodSpec, out *core.PodSpec, s conversion.Scope) error {
  305. if err := autoConvert_v1_PodSpec_To_core_PodSpec(in, out, s); err != nil {
  306. return err
  307. }
  308. // We support DeprecatedServiceAccount as an alias for ServiceAccountName.
  309. // If both are specified, ServiceAccountName (the new field) wins.
  310. if in.ServiceAccountName == "" {
  311. out.ServiceAccountName = in.DeprecatedServiceAccount
  312. }
  313. // the host namespace fields have to be handled specially for backward compatibility
  314. // with v1.0.0
  315. if out.SecurityContext == nil {
  316. out.SecurityContext = new(core.PodSecurityContext)
  317. }
  318. out.SecurityContext.HostNetwork = in.HostNetwork
  319. out.SecurityContext.HostPID = in.HostPID
  320. out.SecurityContext.HostIPC = in.HostIPC
  321. out.SecurityContext.ShareProcessNamespace = in.ShareProcessNamespace
  322. return nil
  323. }
  324. func Convert_v1_Pod_To_core_Pod(in *v1.Pod, out *core.Pod, s conversion.Scope) error {
  325. if err := autoConvert_v1_Pod_To_core_Pod(in, out, s); err != nil {
  326. return err
  327. }
  328. // drop init container annotations so they don't show up as differences when receiving requests from old clients
  329. out.Annotations = dropInitContainerAnnotations(out.Annotations)
  330. return nil
  331. }
  332. func Convert_core_Pod_To_v1_Pod(in *core.Pod, out *v1.Pod, s conversion.Scope) error {
  333. if err := autoConvert_core_Pod_To_v1_Pod(in, out, s); err != nil {
  334. return err
  335. }
  336. // drop init container annotations so they don't take effect on legacy kubelets.
  337. // remove this once the oldest supported kubelet no longer honors the annotations over the field.
  338. out.Annotations = dropInitContainerAnnotations(out.Annotations)
  339. return nil
  340. }
  341. func Convert_v1_Secret_To_core_Secret(in *v1.Secret, out *core.Secret, s conversion.Scope) error {
  342. if err := autoConvert_v1_Secret_To_core_Secret(in, out, s); err != nil {
  343. return err
  344. }
  345. // StringData overwrites Data
  346. if len(in.StringData) > 0 {
  347. if out.Data == nil {
  348. out.Data = map[string][]byte{}
  349. }
  350. for k, v := range in.StringData {
  351. out.Data[k] = []byte(v)
  352. }
  353. }
  354. return nil
  355. }
  356. // +k8s:conversion-fn=copy-only
  357. func Convert_v1_ResourceList_To_core_ResourceList(in *v1.ResourceList, out *core.ResourceList, s conversion.Scope) error {
  358. if *in == nil {
  359. return nil
  360. }
  361. if *out == nil {
  362. *out = make(core.ResourceList, len(*in))
  363. }
  364. for key, val := range *in {
  365. // Moved to defaults
  366. // TODO(#18538): We round up resource values to milli scale to maintain API compatibility.
  367. // In the future, we should instead reject values that need rounding.
  368. // const milliScale = -3
  369. // val.RoundUp(milliScale)
  370. (*out)[core.ResourceName(key)] = val
  371. }
  372. return nil
  373. }
  374. func AddFieldLabelConversionsForEvent(scheme *runtime.Scheme) error {
  375. return scheme.AddFieldLabelConversionFunc(SchemeGroupVersion.WithKind("Event"),
  376. func(label, value string) (string, string, error) {
  377. switch label {
  378. case "involvedObject.kind",
  379. "involvedObject.namespace",
  380. "involvedObject.name",
  381. "involvedObject.uid",
  382. "involvedObject.apiVersion",
  383. "involvedObject.resourceVersion",
  384. "involvedObject.fieldPath",
  385. "reason",
  386. "source",
  387. "type",
  388. "metadata.namespace",
  389. "metadata.name":
  390. return label, value, nil
  391. default:
  392. return "", "", fmt.Errorf("field label not supported: %s", label)
  393. }
  394. })
  395. }
  396. func AddFieldLabelConversionsForNamespace(scheme *runtime.Scheme) error {
  397. return scheme.AddFieldLabelConversionFunc(SchemeGroupVersion.WithKind("Namespace"),
  398. func(label, value string) (string, string, error) {
  399. switch label {
  400. case "status.phase",
  401. "metadata.name":
  402. return label, value, nil
  403. default:
  404. return "", "", fmt.Errorf("field label not supported: %s", label)
  405. }
  406. })
  407. }
  408. func AddFieldLabelConversionsForSecret(scheme *runtime.Scheme) error {
  409. return scheme.AddFieldLabelConversionFunc(SchemeGroupVersion.WithKind("Secret"),
  410. func(label, value string) (string, string, error) {
  411. switch label {
  412. case "type",
  413. "metadata.namespace",
  414. "metadata.name":
  415. return label, value, nil
  416. default:
  417. return "", "", fmt.Errorf("field label not supported: %s", label)
  418. }
  419. })
  420. }
  421. var initContainerAnnotations = map[string]bool{
  422. "pod.beta.kubernetes.io/init-containers": true,
  423. "pod.alpha.kubernetes.io/init-containers": true,
  424. "pod.beta.kubernetes.io/init-container-statuses": true,
  425. "pod.alpha.kubernetes.io/init-container-statuses": true,
  426. }
  427. // dropInitContainerAnnotations returns a copy of the annotations with init container annotations removed,
  428. // or the original annotations if no init container annotations were present.
  429. //
  430. // this can be removed once no clients prior to 1.8 are supported, and no kubelets prior to 1.8 can be run
  431. // (we don't support kubelets older than 2 versions skewed from the apiserver, but we don't prevent them, either)
  432. func dropInitContainerAnnotations(oldAnnotations map[string]string) map[string]string {
  433. if len(oldAnnotations) == 0 {
  434. return oldAnnotations
  435. }
  436. found := false
  437. for k := range initContainerAnnotations {
  438. if _, ok := oldAnnotations[k]; ok {
  439. found = true
  440. break
  441. }
  442. }
  443. if !found {
  444. return oldAnnotations
  445. }
  446. newAnnotations := make(map[string]string, len(oldAnnotations))
  447. for k, v := range oldAnnotations {
  448. if !initContainerAnnotations[k] {
  449. newAnnotations[k] = v
  450. }
  451. }
  452. return newAnnotations
  453. }
  454. // Convert_core_LoadBalancerStatus_To_v1_LoadBalancerStatus is defined outside the autogenerated file for use by other API packages
  455. func Convert_core_LoadBalancerStatus_To_v1_LoadBalancerStatus(in *core.LoadBalancerStatus, out *v1.LoadBalancerStatus, s conversion.Scope) error {
  456. return autoConvert_core_LoadBalancerStatus_To_v1_LoadBalancerStatus(in, out, s)
  457. }
  458. // Convert_v1_LoadBalancerStatus_To_core_LoadBalancerStatus is defined outside the autogenerated file for use by other API packages
  459. func Convert_v1_LoadBalancerStatus_To_core_LoadBalancerStatus(in *v1.LoadBalancerStatus, out *core.LoadBalancerStatus, s conversion.Scope) error {
  460. return autoConvert_v1_LoadBalancerStatus_To_core_LoadBalancerStatus(in, out, s)
  461. }
  462. // Convert_core_Volume_To_v1_Volume is defined outside the autogenerated file for use by other API packages
  463. func Convert_core_Volume_To_v1_Volume(in *core.Volume, out *v1.Volume, s conversion.Scope) error {
  464. return autoConvert_core_Volume_To_v1_Volume(in, out, s)
  465. }
  466. // Convert_v1_Volume_To_core_Volume is defined outside the autogenerated file for use by other API packages
  467. func Convert_v1_Volume_To_core_Volume(in *v1.Volume, out *core.Volume, s conversion.Scope) error {
  468. return autoConvert_v1_Volume_To_core_Volume(in, out, s)
  469. }
  470. // Convert_core_PersistentVolumeSpec_To_v1_PersistentVolumeSpec is defined outside the autogenerated file for use by other API packages
  471. func Convert_core_PersistentVolumeSpec_To_v1_PersistentVolumeSpec(in *core.PersistentVolumeSpec, out *v1.PersistentVolumeSpec, s conversion.Scope) error {
  472. return autoConvert_core_PersistentVolumeSpec_To_v1_PersistentVolumeSpec(in, out, s)
  473. }
  474. // Convert_v1_PersistentVolumeSpec_To_core_PersistentVolumeSpec is defined outside the autogenerated file for use by other API packages
  475. func Convert_v1_PersistentVolumeSpec_To_core_PersistentVolumeSpec(in *v1.PersistentVolumeSpec, out *core.PersistentVolumeSpec, s conversion.Scope) error {
  476. return autoConvert_v1_PersistentVolumeSpec_To_core_PersistentVolumeSpec(in, out, s)
  477. }