github.com/imran-kn/cilium-fork@v1.6.9/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  }