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