github.phpd.cn/cilium/cilium@v1.6.12/pkg/k8s/factory_functions.go (about) 1 // Copyright 2018-2019 Authors of Cilium 2 // 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 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package k8s 16 17 import ( 18 "reflect" 19 20 "github.com/cilium/cilium/pkg/annotation" 21 "github.com/cilium/cilium/pkg/comparator" 22 cilium_v2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" 23 "github.com/cilium/cilium/pkg/k8s/types" 24 "github.com/cilium/cilium/pkg/logging/logfields" 25 26 "k8s.io/api/core/v1" 27 "k8s.io/api/extensions/v1beta1" 28 networkingv1 "k8s.io/api/networking/v1" 29 "k8s.io/client-go/tools/cache" 30 ) 31 32 func CopyObjToV1NetworkPolicy(obj interface{}) *types.NetworkPolicy { 33 k8sNP, ok := obj.(*types.NetworkPolicy) 34 if !ok { 35 log.WithField(logfields.Object, logfields.Repr(obj)). 36 Warn("Ignoring invalid k8s v1 NetworkPolicy") 37 return nil 38 } 39 return k8sNP.DeepCopy() 40 } 41 42 func CopyObjToV1Services(obj interface{}) *types.Service { 43 svc, ok := obj.(*types.Service) 44 if !ok { 45 log.WithField(logfields.Object, logfields.Repr(obj)). 46 Warn("Ignoring invalid k8s v1 Service") 47 return nil 48 } 49 return svc.DeepCopy() 50 } 51 52 func CopyObjToV1Endpoints(obj interface{}) *types.Endpoints { 53 ep, ok := obj.(*types.Endpoints) 54 if !ok { 55 log.WithField(logfields.Object, logfields.Repr(obj)). 56 Warn("Ignoring invalid k8s v1 Endpoints") 57 return nil 58 } 59 return ep.DeepCopy() 60 } 61 62 func CopyObjToV1beta1Ingress(obj interface{}) *types.Ingress { 63 ing, ok := obj.(*types.Ingress) 64 if !ok { 65 log.WithField(logfields.Object, logfields.Repr(obj)). 66 Warn("Ignoring invalid k8s v1beta1 Ingress") 67 return nil 68 } 69 return ing.DeepCopy() 70 } 71 72 func CopyObjToV2CNP(obj interface{}) *types.SlimCNP { 73 cnp, ok := obj.(*types.SlimCNP) 74 if !ok { 75 log.WithField(logfields.Object, logfields.Repr(obj)). 76 Warn("Ignoring invalid k8s v2 CiliumNetworkPolicy") 77 return nil 78 } 79 return cnp.DeepCopy() 80 } 81 82 func CopyObjToV1Pod(obj interface{}) *types.Pod { 83 pod, ok := obj.(*types.Pod) 84 if !ok { 85 log.WithField(logfields.Object, logfields.Repr(obj)). 86 Warn("Ignoring invalid k8s v1 Pod") 87 return nil 88 } 89 return pod.DeepCopy() 90 } 91 92 func CopyObjToV1Node(obj interface{}) *types.Node { 93 node, ok := obj.(*types.Node) 94 if !ok { 95 log.WithField(logfields.Object, logfields.Repr(obj)). 96 Warn("Ignoring invalid k8s v1 Node") 97 return nil 98 } 99 return node.DeepCopy() 100 } 101 102 func CopyObjToV1Namespace(obj interface{}) *types.Namespace { 103 ns, ok := obj.(*types.Namespace) 104 if !ok { 105 log.WithField(logfields.Object, logfields.Repr(obj)). 106 Warn("Ignoring invalid k8s v1 Namespace") 107 return nil 108 } 109 return ns.DeepCopy() 110 } 111 112 func EqualV1NetworkPolicy(np1, np2 *types.NetworkPolicy) bool { 113 // As Cilium uses all of the Spec from a NP it's not probably not worth 114 // it to create a dedicated deep equal function to compare both network 115 // policies. 116 return np1.Name == np2.Name && 117 np1.Namespace == np2.Namespace && 118 reflect.DeepEqual(np1.Spec, np2.Spec) 119 } 120 121 func EqualV1Services(k8sSVC1, k8sSVC2 *types.Service) bool { 122 // Service annotations are used to mark services as global, shared, etc. 123 if !comparator.MapStringEquals(k8sSVC1.GetAnnotations(), k8sSVC2.GetAnnotations()) { 124 return false 125 } 126 127 svcID1, svc1 := ParseService(k8sSVC1) 128 svcID2, svc2 := ParseService(k8sSVC2) 129 130 if svcID1 != svcID2 { 131 return false 132 } 133 134 // Please write all the equalness logic inside the K8sServiceInfo.Equals() 135 // method. 136 return svc1.DeepEquals(svc2) 137 } 138 139 func EqualV1Endpoints(ep1, ep2 *types.Endpoints) bool { 140 // We only care about the Name, Namespace and Subsets of a particular 141 // endpoint. 142 return ep1.Name == ep2.Name && 143 ep1.Namespace == ep2.Namespace && 144 reflect.DeepEqual(ep1.Subsets, ep2.Subsets) 145 } 146 147 func EqualV1beta1Ingress(ing1, ing2 *types.Ingress) bool { 148 if ing1.Name != ing2.Name || ing1.Namespace != ing2.Namespace { 149 return false 150 } 151 switch { 152 case (ing1.Spec.Backend == nil) != (ing2.Spec.Backend == nil): 153 return false 154 case (ing1.Spec.Backend == nil) && (ing2.Spec.Backend == nil): 155 return true 156 } 157 158 return ing1.Spec.Backend.ServicePort.IntVal == 159 ing2.Spec.Backend.ServicePort.IntVal && 160 ing1.Spec.Backend.ServicePort.StrVal == 161 ing2.Spec.Backend.ServicePort.StrVal 162 } 163 164 func EqualV2CNP(cnp1, cnp2 *types.SlimCNP) bool { 165 if !(cnp1.Name == cnp2.Name && cnp1.Namespace == cnp2.Namespace) { 166 return false 167 } 168 169 // Ignore v1.LastAppliedConfigAnnotation annotation 170 lastAppliedCfgAnnotation1, ok1 := cnp1.GetAnnotations()[v1.LastAppliedConfigAnnotation] 171 lastAppliedCfgAnnotation2, ok2 := cnp2.GetAnnotations()[v1.LastAppliedConfigAnnotation] 172 defer func() { 173 if ok1 && cnp1.GetAnnotations() != nil { 174 cnp1.GetAnnotations()[v1.LastAppliedConfigAnnotation] = lastAppliedCfgAnnotation1 175 } 176 if ok2 && cnp2.GetAnnotations() != nil { 177 cnp2.GetAnnotations()[v1.LastAppliedConfigAnnotation] = lastAppliedCfgAnnotation2 178 } 179 }() 180 delete(cnp1.GetAnnotations(), v1.LastAppliedConfigAnnotation) 181 delete(cnp2.GetAnnotations(), v1.LastAppliedConfigAnnotation) 182 183 return comparator.MapStringEquals(cnp1.GetAnnotations(), cnp2.GetAnnotations()) && 184 reflect.DeepEqual(cnp1.Spec, cnp2.Spec) && 185 reflect.DeepEqual(cnp1.Specs, cnp2.Specs) 186 } 187 188 func EqualV1Pod(pod1, pod2 *types.Pod) bool { 189 // We only care about the HostIP, the PodIP and the labels of the pods. 190 if pod1.StatusPodIP != pod2.StatusPodIP || 191 pod1.StatusHostIP != pod2.StatusHostIP { 192 return false 193 } 194 oldPodLabels := pod1.GetLabels() 195 newPodLabels := pod2.GetLabels() 196 return comparator.MapStringEquals(oldPodLabels, newPodLabels) 197 } 198 199 func EqualV1Node(node1, node2 *types.Node) bool { 200 if node1.GetObjectMeta().GetName() != node2.GetObjectMeta().GetName() { 201 return false 202 } 203 204 anno1 := node1.GetAnnotations() 205 anno2 := node2.GetAnnotations() 206 annotationsWeCareAbout := []string{ 207 annotation.CiliumHostIP, 208 annotation.CiliumHostIPv6, 209 annotation.V4HealthName, 210 annotation.V6HealthName, 211 } 212 for _, an := range annotationsWeCareAbout { 213 if anno1[an] != anno2[an] { 214 return false 215 } 216 } 217 if len(node1.SpecTaints) != len(node2.SpecTaints) { 218 return false 219 } 220 for i, taint2 := range node2.SpecTaints { 221 taint1 := node1.SpecTaints[i] 222 if !taint1.MatchTaint(&taint2) { 223 return false 224 } 225 if taint1.Value != taint2.Value { 226 return false 227 } 228 if !taint1.TimeAdded.Equal(taint2.TimeAdded) { 229 return false 230 } 231 } 232 return true 233 } 234 235 func EqualV1Namespace(ns1, ns2 *types.Namespace) bool { 236 // we only care about namespace labels. 237 return ns1.Name == ns2.Name && 238 comparator.MapStringEquals(ns1.GetLabels(), ns2.GetLabels()) 239 } 240 241 // ConvertToNetworkPolicy converts a *networkingv1.NetworkPolicy into a 242 // *types.NetworkPolicy or a cache.DeletedFinalStateUnknown into 243 // a cache.DeletedFinalStateUnknown with a *types.NetworkPolicy in its Obj. 244 // If the given obj can't be cast into either *networkingv1.NetworkPolicy 245 // nor cache.DeletedFinalStateUnknown, the original obj is returned. 246 func ConvertToNetworkPolicy(obj interface{}) interface{} { 247 // TODO check which fields we really need 248 switch concreteObj := obj.(type) { 249 case *networkingv1.NetworkPolicy: 250 return &types.NetworkPolicy{ 251 NetworkPolicy: concreteObj, 252 } 253 case cache.DeletedFinalStateUnknown: 254 netPol, ok := concreteObj.Obj.(*networkingv1.NetworkPolicy) 255 if !ok { 256 return obj 257 } 258 return cache.DeletedFinalStateUnknown{ 259 Key: concreteObj.Key, 260 Obj: &types.NetworkPolicy{ 261 NetworkPolicy: netPol, 262 }, 263 } 264 default: 265 return obj 266 } 267 } 268 269 // ConvertToK8sService converts a *v1.Service into a 270 // *types.Service or a cache.DeletedFinalStateUnknown into 271 // a cache.DeletedFinalStateUnknown with a *types.Service in its Obj. 272 // If the given obj can't be cast into either *v1.Service 273 // nor cache.DeletedFinalStateUnknown, the original obj is returned. 274 func ConvertToK8sService(obj interface{}) interface{} { 275 // TODO check which fields we really need 276 switch concreteObj := obj.(type) { 277 case *v1.Service: 278 return &types.Service{ 279 Service: concreteObj, 280 } 281 case cache.DeletedFinalStateUnknown: 282 svc, ok := concreteObj.Obj.(*v1.Service) 283 if !ok { 284 return obj 285 } 286 return cache.DeletedFinalStateUnknown{ 287 Key: concreteObj.Key, 288 Obj: &types.Service{ 289 Service: svc, 290 }, 291 } 292 default: 293 return obj 294 } 295 } 296 297 // ConvertToK8sEndpoints converts a *v1.Endpoints into a 298 // *types.Endpoints or a cache.DeletedFinalStateUnknown into 299 // a cache.DeletedFinalStateUnknown with a *types.Endpoints in its Obj. 300 // If the given obj can't be cast into either *v1.Endpoints 301 // nor cache.DeletedFinalStateUnknown, the original obj is returned. 302 func ConvertToK8sEndpoints(obj interface{}) interface{} { 303 // TODO check which fields we really need 304 switch concreteObj := obj.(type) { 305 case *v1.Endpoints: 306 return &types.Endpoints{ 307 Endpoints: concreteObj, 308 } 309 case cache.DeletedFinalStateUnknown: 310 eps, ok := concreteObj.Obj.(*v1.Endpoints) 311 if !ok { 312 return obj 313 } 314 return cache.DeletedFinalStateUnknown{ 315 Key: concreteObj.Key, 316 Obj: &types.Endpoints{ 317 Endpoints: eps, 318 }, 319 } 320 default: 321 return obj 322 } 323 } 324 325 // ConvertToIngress converts a *v1beta1.Ingress into a 326 // *types.Ingress or a cache.DeletedFinalStateUnknown into 327 // a cache.DeletedFinalStateUnknown with a *types.Ingress in its Obj. 328 // If the given obj can't be cast into either *v1beta1.Ingress 329 // nor cache.DeletedFinalStateUnknown, the original obj is returned. 330 func ConvertToIngress(obj interface{}) interface{} { 331 // TODO check which fields we really need 332 switch concreteObj := obj.(type) { 333 case *v1beta1.Ingress: 334 return &types.Ingress{ 335 Ingress: concreteObj, 336 } 337 case cache.DeletedFinalStateUnknown: 338 ingrss, ok := concreteObj.Obj.(*v1beta1.Ingress) 339 if !ok { 340 return obj 341 } 342 return cache.DeletedFinalStateUnknown{ 343 Key: concreteObj.Key, 344 Obj: &types.Ingress{ 345 Ingress: ingrss, 346 }, 347 } 348 default: 349 return obj 350 } 351 } 352 353 // ConvertToCNPWithStatus converts a *cilium_v2.CiliumNetworkPolicy into a 354 // *types.SlimCNP or a cache.DeletedFinalStateUnknown into 355 // a cache.DeletedFinalStateUnknown with a *types.SlimCNP in its Obj. 356 // If the given obj can't be cast into either *cilium_v2.CiliumNetworkPolicy 357 // nor cache.DeletedFinalStateUnknown, the original obj is returned. 358 func ConvertToCNPWithStatus(obj interface{}) interface{} { 359 switch concreteObj := obj.(type) { 360 case *cilium_v2.CiliumNetworkPolicy: 361 return &types.SlimCNP{ 362 CiliumNetworkPolicy: concreteObj, 363 } 364 case cache.DeletedFinalStateUnknown: 365 cnp, ok := concreteObj.Obj.(*cilium_v2.CiliumNetworkPolicy) 366 if !ok { 367 return obj 368 } 369 return cache.DeletedFinalStateUnknown{ 370 Key: concreteObj.Key, 371 Obj: &types.SlimCNP{ 372 CiliumNetworkPolicy: cnp, 373 }, 374 } 375 default: 376 return obj 377 } 378 } 379 380 // ConvertToCNP converts a *cilium_v2.CiliumNetworkPolicy into a 381 // *types.SlimCNP without the Status field of the given CNP, or a 382 // cache.DeletedFinalStateUnknown into a cache.DeletedFinalStateUnknown with a 383 // *types.SlimCNP, also without the Status field of the given CNP, in its Obj. 384 // If the given obj can't be cast into either *cilium_v2.CiliumNetworkPolicy 385 // nor cache.DeletedFinalStateUnknown, the original obj is returned. 386 // WARNING calling this function will set *all* fields of the given CNP as 387 // empty. 388 func ConvertToCNP(obj interface{}) interface{} { 389 switch concreteObj := obj.(type) { 390 case *cilium_v2.CiliumNetworkPolicy: 391 cnp := &types.SlimCNP{ 392 CiliumNetworkPolicy: &cilium_v2.CiliumNetworkPolicy{ 393 TypeMeta: concreteObj.TypeMeta, 394 ObjectMeta: concreteObj.ObjectMeta, 395 Spec: concreteObj.Spec, 396 Specs: concreteObj.Specs, 397 }, 398 } 399 *concreteObj = cilium_v2.CiliumNetworkPolicy{} 400 return cnp 401 case cache.DeletedFinalStateUnknown: 402 cnp, ok := concreteObj.Obj.(*cilium_v2.CiliumNetworkPolicy) 403 if !ok { 404 return obj 405 } 406 dfsu := cache.DeletedFinalStateUnknown{ 407 Key: concreteObj.Key, 408 Obj: &types.SlimCNP{ 409 CiliumNetworkPolicy: &cilium_v2.CiliumNetworkPolicy{ 410 TypeMeta: cnp.TypeMeta, 411 ObjectMeta: cnp.ObjectMeta, 412 Spec: cnp.Spec, 413 Specs: cnp.Specs, 414 }, 415 }, 416 } 417 *cnp = cilium_v2.CiliumNetworkPolicy{} 418 return dfsu 419 default: 420 return obj 421 } 422 } 423 424 // ConvertToPod converts a *v1.Pod into a 425 // *types.Pod or a cache.DeletedFinalStateUnknown into 426 // a cache.DeletedFinalStateUnknown with a *types.Pod in its Obj. 427 // If the given obj can't be cast into either *v1.Pod 428 // nor cache.DeletedFinalStateUnknown, the original obj is returned. 429 // WARNING calling this function will set *all* fields of the given Pod as 430 // empty. 431 func ConvertToPod(obj interface{}) interface{} { 432 switch concreteObj := obj.(type) { 433 case *v1.Pod: 434 p := &types.Pod{ 435 TypeMeta: concreteObj.TypeMeta, 436 ObjectMeta: concreteObj.ObjectMeta, 437 StatusPodIP: concreteObj.Status.PodIP, 438 StatusHostIP: concreteObj.Status.HostIP, 439 SpecHostNetwork: concreteObj.Spec.HostNetwork, 440 } 441 *concreteObj = v1.Pod{} 442 return p 443 case cache.DeletedFinalStateUnknown: 444 pod, ok := concreteObj.Obj.(*v1.Pod) 445 if !ok { 446 return obj 447 } 448 dfsu := cache.DeletedFinalStateUnknown{ 449 Key: concreteObj.Key, 450 Obj: &types.Pod{ 451 TypeMeta: pod.TypeMeta, 452 ObjectMeta: pod.ObjectMeta, 453 StatusPodIP: pod.Status.PodIP, 454 StatusHostIP: pod.Status.HostIP, 455 SpecHostNetwork: pod.Spec.HostNetwork, 456 }, 457 } 458 *pod = v1.Pod{} 459 return dfsu 460 default: 461 return obj 462 } 463 } 464 465 // ConvertToNode converts a *v1.Node into a 466 // *types.Node or a cache.DeletedFinalStateUnknown into 467 // a cache.DeletedFinalStateUnknown with a *types.Node in its Obj. 468 // If the given obj can't be cast into either *v1.Node 469 // nor cache.DeletedFinalStateUnknown, the original obj is returned. 470 // WARNING calling this function will set *all* fields of the given Node as 471 // empty. 472 func ConvertToNode(obj interface{}) interface{} { 473 switch concreteObj := obj.(type) { 474 case *v1.Node: 475 p := &types.Node{ 476 TypeMeta: concreteObj.TypeMeta, 477 ObjectMeta: concreteObj.ObjectMeta, 478 StatusAddresses: concreteObj.Status.Addresses, 479 SpecPodCIDR: concreteObj.Spec.PodCIDR, 480 SpecTaints: concreteObj.Spec.Taints, 481 } 482 *concreteObj = v1.Node{} 483 return p 484 case cache.DeletedFinalStateUnknown: 485 node, ok := concreteObj.Obj.(*v1.Node) 486 if !ok { 487 return obj 488 } 489 dfsu := cache.DeletedFinalStateUnknown{ 490 Key: concreteObj.Key, 491 Obj: &types.Node{ 492 TypeMeta: node.TypeMeta, 493 ObjectMeta: node.ObjectMeta, 494 StatusAddresses: node.Status.Addresses, 495 SpecPodCIDR: node.Spec.PodCIDR, 496 SpecTaints: node.Spec.Taints, 497 }, 498 } 499 *node = v1.Node{} 500 return dfsu 501 default: 502 return obj 503 } 504 } 505 506 // ConvertToNamespace converts a *v1.Namespace into a 507 // *types.Namespace or a cache.DeletedFinalStateUnknown into 508 // a cache.DeletedFinalStateUnknown with a *types.Namespace in its Obj. 509 // If the given obj can't be cast into either *v1.Namespace 510 // nor cache.DeletedFinalStateUnknown, the original obj is returned. 511 // WARNING calling this function will set *all* fields of the given Namespace as 512 // empty. 513 func ConvertToNamespace(obj interface{}) interface{} { 514 switch concreteObj := obj.(type) { 515 case *v1.Namespace: 516 p := &types.Namespace{ 517 TypeMeta: concreteObj.TypeMeta, 518 ObjectMeta: concreteObj.ObjectMeta, 519 } 520 *concreteObj = v1.Namespace{} 521 return p 522 case cache.DeletedFinalStateUnknown: 523 namespace, ok := concreteObj.Obj.(*v1.Namespace) 524 if !ok { 525 return obj 526 } 527 dfsu := cache.DeletedFinalStateUnknown{ 528 Key: concreteObj.Key, 529 Obj: &types.Namespace{ 530 TypeMeta: namespace.TypeMeta, 531 ObjectMeta: namespace.ObjectMeta, 532 }, 533 } 534 *namespace = v1.Namespace{} 535 return dfsu 536 default: 537 return obj 538 } 539 } 540 541 // ConvertToCiliumNode converts a *cilium_v2.CiliumNode into a 542 // *cilium_v2.CiliumNode or a cache.DeletedFinalStateUnknown into 543 // a cache.DeletedFinalStateUnknown with a *cilium_v2.CiliumNode in its Obj. 544 // If the given obj can't be cast into either *cilium_v2.CiliumNode 545 // nor cache.DeletedFinalStateUnknown, the original obj is returned. 546 func ConvertToCiliumNode(obj interface{}) interface{} { 547 // TODO create a slim type of the CiliumNode 548 switch concreteObj := obj.(type) { 549 case *cilium_v2.CiliumNode: 550 return concreteObj 551 case cache.DeletedFinalStateUnknown: 552 ciliumNode, ok := concreteObj.Obj.(*cilium_v2.CiliumNode) 553 if !ok { 554 return obj 555 } 556 return cache.DeletedFinalStateUnknown{ 557 Key: concreteObj.Key, 558 Obj: ciliumNode, 559 } 560 default: 561 return obj 562 } 563 } 564 565 // CopyObjToCiliumNode attempts to cast object to a CiliumNode object and 566 // returns a deep copy if the castin succeeds. Otherwise, nil is returned. 567 func CopyObjToCiliumNode(obj interface{}) *cilium_v2.CiliumNode { 568 cn, ok := obj.(*cilium_v2.CiliumNode) 569 if !ok { 570 log.WithField(logfields.Object, logfields.Repr(obj)). 571 Warn("Ignoring invalid CiliumNode") 572 return nil 573 } 574 return cn.DeepCopy() 575 } 576 577 // ConvertToCiliumEndpoint converts a *cilium_v2.CiliumEndpoint into a 578 // *types.CiliumEndpoint or a cache.DeletedFinalStateUnknown into a 579 // cache.DeletedFinalStateUnknown with a *types.CiliumEndpoint in its Obj. 580 // If the given obj can't be cast into either *cilium_v2.CiliumEndpoint nor 581 // cache.DeletedFinalStateUnknown, the original obj is returned. 582 func ConvertToCiliumEndpoint(obj interface{}) interface{} { 583 switch concreteObj := obj.(type) { 584 case *cilium_v2.CiliumEndpoint: 585 p := &types.CiliumEndpoint{ 586 TypeMeta: concreteObj.TypeMeta, 587 ObjectMeta: concreteObj.ObjectMeta, 588 Encryption: concreteObj.Status.Encryption.DeepCopy(), 589 Identity: concreteObj.Status.Identity.DeepCopy(), 590 Networking: concreteObj.Status.Networking.DeepCopy(), 591 } 592 *concreteObj = cilium_v2.CiliumEndpoint{} 593 return p 594 case cache.DeletedFinalStateUnknown: 595 ciliumEndpoint, ok := concreteObj.Obj.(*cilium_v2.CiliumEndpoint) 596 if !ok { 597 return obj 598 } 599 dfsu := cache.DeletedFinalStateUnknown{ 600 Key: concreteObj.Key, 601 Obj: &types.CiliumEndpoint{ 602 TypeMeta: ciliumEndpoint.TypeMeta, 603 ObjectMeta: ciliumEndpoint.ObjectMeta, 604 Encryption: ciliumEndpoint.Status.Encryption.DeepCopy(), 605 Identity: ciliumEndpoint.Status.Identity.DeepCopy(), 606 Networking: ciliumEndpoint.Status.Networking.DeepCopy(), 607 }, 608 } 609 *ciliumEndpoint = cilium_v2.CiliumEndpoint{} 610 return dfsu 611 default: 612 return obj 613 } 614 } 615 616 // CopyObjToCiliumEndpoint attempts to cast object to a CiliumEndpoint object 617 // and returns a deep copy if the castin succeeds. Otherwise, nil is returned. 618 func CopyObjToCiliumEndpoint(obj interface{}) *types.CiliumEndpoint { 619 ce, ok := obj.(*types.CiliumEndpoint) 620 if !ok { 621 log.WithField(logfields.Object, logfields.Repr(obj)). 622 Warn("Ignoring invalid CiliumEndpoint") 623 return nil 624 } 625 return ce.DeepCopy() 626 }