github.com/cilium/cilium@v1.16.2/pkg/k8s/factory_functions.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package k8s
     5  
     6  import (
     7  	"fmt"
     8  
     9  	v1 "k8s.io/api/core/v1"
    10  	networkingv1 "k8s.io/api/networking/v1"
    11  	"k8s.io/client-go/tools/cache"
    12  
    13  	cilium_v2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2"
    14  	cilium_v2alpha1 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1"
    15  	slim_corev1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/api/core/v1"
    16  	slim_metav1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1"
    17  	"github.com/cilium/cilium/pkg/k8s/types"
    18  )
    19  
    20  // AnnotationsEqual returns whether the annotation with any key in
    21  // relevantAnnotations is equal in anno1 and anno2.
    22  func AnnotationsEqual(relevantAnnotations []string, anno1, anno2 map[string]string) bool {
    23  	for _, an := range relevantAnnotations {
    24  		if anno1[an] != anno2[an] {
    25  			return false
    26  		}
    27  	}
    28  	return true
    29  }
    30  
    31  func ConvertToK8sV1ServicePorts(slimPorts []slim_corev1.ServicePort) []v1.ServicePort {
    32  	if slimPorts == nil {
    33  		return nil
    34  	}
    35  
    36  	ports := make([]v1.ServicePort, 0, len(slimPorts))
    37  	for _, port := range slimPorts {
    38  		ports = append(ports,
    39  			v1.ServicePort{
    40  				Name:     port.Name,
    41  				Protocol: v1.Protocol(port.Protocol),
    42  				Port:     port.Port,
    43  				NodePort: port.NodePort,
    44  			},
    45  		)
    46  	}
    47  	return ports
    48  }
    49  
    50  func ConvertToK8sV1ServiceAffinityConfig(saCfg *slim_corev1.SessionAffinityConfig) *v1.SessionAffinityConfig {
    51  	if saCfg == nil {
    52  		return nil
    53  	}
    54  
    55  	if saCfg.ClientIP == nil {
    56  		return &v1.SessionAffinityConfig{}
    57  	}
    58  
    59  	return &v1.SessionAffinityConfig{
    60  		ClientIP: &v1.ClientIPConfig{
    61  			TimeoutSeconds: saCfg.ClientIP.TimeoutSeconds,
    62  		},
    63  	}
    64  }
    65  
    66  func ConvertToK8sV1LoadBalancerIngress(slimLBIngs []slim_corev1.LoadBalancerIngress) []v1.LoadBalancerIngress {
    67  	if slimLBIngs == nil {
    68  		return nil
    69  	}
    70  
    71  	lbIngs := make([]v1.LoadBalancerIngress, 0, len(slimLBIngs))
    72  	for _, lbIng := range slimLBIngs {
    73  		var ports []v1.PortStatus
    74  		for _, port := range lbIng.Ports {
    75  			ports = append(ports, v1.PortStatus{
    76  				Port:     port.Port,
    77  				Protocol: v1.Protocol(port.Protocol),
    78  				Error:    port.Error,
    79  			})
    80  		}
    81  		lbIngs = append(lbIngs,
    82  			v1.LoadBalancerIngress{
    83  				IP:       lbIng.IP,
    84  				Hostname: lbIng.Hostname,
    85  				Ports:    ports,
    86  			},
    87  		)
    88  	}
    89  	return lbIngs
    90  }
    91  
    92  func ConvertToNetworkV1IngressLoadBalancerIngress(slimLBIngs []slim_corev1.LoadBalancerIngress) []networkingv1.IngressLoadBalancerIngress {
    93  	if slimLBIngs == nil {
    94  		return nil
    95  	}
    96  
    97  	ingLBIngs := make([]networkingv1.IngressLoadBalancerIngress, 0, len(slimLBIngs))
    98  	for _, lbIng := range slimLBIngs {
    99  		ports := make([]networkingv1.IngressPortStatus, 0, len(lbIng.Ports))
   100  		for _, port := range lbIng.Ports {
   101  			ports = append(ports, networkingv1.IngressPortStatus{
   102  				Port:     port.Port,
   103  				Protocol: v1.Protocol(port.Protocol),
   104  				Error:    port.Error,
   105  			})
   106  		}
   107  		ingLBIngs = append(ingLBIngs,
   108  			networkingv1.IngressLoadBalancerIngress{
   109  				IP:       lbIng.IP,
   110  				Hostname: lbIng.Hostname,
   111  				Ports:    ports,
   112  			})
   113  	}
   114  	return ingLBIngs
   115  }
   116  
   117  // TransformToCCNP transforms a *cilium_v2.CiliumClusterwideNetworkPolicy into a
   118  // *types.SlimCNP without the Status field of the given CNP, or a
   119  // cache.DeletedFinalStateUnknown into a cache.DeletedFinalStateUnknown with a
   120  // *types.SlimCNP, also without the Status field of the given CNP, in its Obj.
   121  // If obj is a *types.SlimCNP or a cache.DeletedFinalStateUnknown with a *types.SlimCNP
   122  // in its Obj, obj is returned without any transformations. If the given obj can't be
   123  // cast into either *cilium_v2.CiliumClusterwideNetworkPolicy nor
   124  // cache.DeletedFinalStateUnknown, an error is returned.
   125  func TransformToCCNP(obj interface{}) (interface{}, error) {
   126  	switch concreteObj := obj.(type) {
   127  	case *cilium_v2.CiliumClusterwideNetworkPolicy:
   128  		return &types.SlimCNP{
   129  			CiliumNetworkPolicy: &cilium_v2.CiliumNetworkPolicy{
   130  				TypeMeta:   concreteObj.TypeMeta,
   131  				ObjectMeta: concreteObj.ObjectMeta,
   132  				Spec:       concreteObj.Spec,
   133  				Specs:      concreteObj.Specs,
   134  			},
   135  		}, nil
   136  	case *types.SlimCNP:
   137  		return obj, nil
   138  	case cache.DeletedFinalStateUnknown:
   139  		if _, ok := concreteObj.Obj.(*types.SlimCNP); ok {
   140  			return obj, nil
   141  		}
   142  		ccnp, ok := concreteObj.Obj.(*cilium_v2.CiliumClusterwideNetworkPolicy)
   143  		if !ok {
   144  			return nil, fmt.Errorf("unknown object type %T", concreteObj.Obj)
   145  		}
   146  		slimCNP := &types.SlimCNP{
   147  			CiliumNetworkPolicy: &cilium_v2.CiliumNetworkPolicy{
   148  				TypeMeta:   ccnp.TypeMeta,
   149  				ObjectMeta: ccnp.ObjectMeta,
   150  				Spec:       ccnp.Spec,
   151  				Specs:      ccnp.Specs,
   152  			},
   153  		}
   154  		dfsu := cache.DeletedFinalStateUnknown{
   155  			Key: concreteObj.Key,
   156  			Obj: slimCNP,
   157  		}
   158  		return dfsu, nil
   159  
   160  	default:
   161  		return nil, fmt.Errorf("unknown object type %T", concreteObj)
   162  	}
   163  }
   164  
   165  // TransformToCNP transforms a *cilium_v2.CiliumNetworkPolicy into a
   166  // *types.SlimCNP without the Status field of the given CNP, or a
   167  // cache.DeletedFinalStateUnknown into a cache.DeletedFinalStateUnknown with a
   168  // *types.SlimCNP, also without the Status field of the given CNP, in its Obj.
   169  // If obj is a *types.SlimCNP or a cache.DeletedFinalStateUnknown with a
   170  // *types.SlimCNP in its Obj, obj is returned without any transformations.
   171  // If the given obj can't be cast into either *cilium_v2.CiliumNetworkPolicy
   172  // nor cache.DeletedFinalStateUnknown, an error is returned.
   173  func TransformToCNP(obj interface{}) (interface{}, error) {
   174  	switch concreteObj := obj.(type) {
   175  	case *cilium_v2.CiliumNetworkPolicy:
   176  		return &types.SlimCNP{
   177  			CiliumNetworkPolicy: &cilium_v2.CiliumNetworkPolicy{
   178  				TypeMeta:   concreteObj.TypeMeta,
   179  				ObjectMeta: concreteObj.ObjectMeta,
   180  				Spec:       concreteObj.Spec,
   181  				Specs:      concreteObj.Specs,
   182  			},
   183  		}, nil
   184  	case *types.SlimCNP:
   185  		return obj, nil
   186  	case cache.DeletedFinalStateUnknown:
   187  		if _, ok := concreteObj.Obj.(*types.SlimCNP); ok {
   188  			return obj, nil
   189  		}
   190  		cnp, ok := concreteObj.Obj.(*cilium_v2.CiliumNetworkPolicy)
   191  		if !ok {
   192  			return nil, fmt.Errorf("unknown object type %T", concreteObj.Obj)
   193  		}
   194  		return cache.DeletedFinalStateUnknown{
   195  			Key: concreteObj.Key,
   196  			Obj: &types.SlimCNP{
   197  				CiliumNetworkPolicy: &cilium_v2.CiliumNetworkPolicy{
   198  					TypeMeta:   cnp.TypeMeta,
   199  					ObjectMeta: cnp.ObjectMeta,
   200  					Spec:       cnp.Spec,
   201  					Specs:      cnp.Specs,
   202  				},
   203  			},
   204  		}, nil
   205  	default:
   206  		return nil, fmt.Errorf("unknown object type %T", concreteObj)
   207  	}
   208  }
   209  
   210  func convertToAddress(v1Addrs []v1.NodeAddress) []slim_corev1.NodeAddress {
   211  	if v1Addrs == nil {
   212  		return nil
   213  	}
   214  
   215  	addrs := make([]slim_corev1.NodeAddress, 0, len(v1Addrs))
   216  	for _, addr := range v1Addrs {
   217  		addrs = append(
   218  			addrs,
   219  			slim_corev1.NodeAddress{
   220  				Type:    slim_corev1.NodeAddressType(addr.Type),
   221  				Address: addr.Address,
   222  			},
   223  		)
   224  	}
   225  	return addrs
   226  }
   227  
   228  func convertToTaints(v1Taints []v1.Taint) []slim_corev1.Taint {
   229  	if v1Taints == nil {
   230  		return nil
   231  	}
   232  
   233  	taints := make([]slim_corev1.Taint, 0, len(v1Taints))
   234  	for _, taint := range v1Taints {
   235  		var ta *slim_metav1.Time
   236  		if taint.TimeAdded != nil {
   237  			t := slim_metav1.NewTime(taint.TimeAdded.Time)
   238  			ta = &t
   239  		}
   240  		taints = append(
   241  			taints,
   242  			slim_corev1.Taint{
   243  				Key:       taint.Key,
   244  				Value:     taint.Value,
   245  				Effect:    slim_corev1.TaintEffect(taint.Effect),
   246  				TimeAdded: ta,
   247  			},
   248  		)
   249  	}
   250  	return taints
   251  }
   252  
   253  // TransformToCiliumEndpoint transforms a *cilium_v2.CiliumEndpoint into a
   254  // *types.CiliumEndpoint or a cache.DeletedFinalStateUnknown into a
   255  // cache.DeletedFinalStateUnknown with a *types.CiliumEndpoint in its Obj.
   256  // If obj is a *types.CiliumEndpoint or a cache.DeletedFinalStateUnknown with
   257  // a *types.CiliumEndpoint in its Obj, obj is returned without any transformations.
   258  // If the given obj can't be cast into either *cilium_v2.CiliumEndpoint nor
   259  // cache.DeletedFinalStateUnknown, an error is returned.
   260  func TransformToCiliumEndpoint(obj interface{}) (interface{}, error) {
   261  	switch concreteObj := obj.(type) {
   262  	case *cilium_v2.CiliumEndpoint:
   263  		return &types.CiliumEndpoint{
   264  			TypeMeta: slim_metav1.TypeMeta{
   265  				Kind:       concreteObj.TypeMeta.Kind,
   266  				APIVersion: concreteObj.TypeMeta.APIVersion,
   267  			},
   268  			ObjectMeta: slim_metav1.ObjectMeta{
   269  				Name:            concreteObj.ObjectMeta.Name,
   270  				Namespace:       concreteObj.ObjectMeta.Namespace,
   271  				UID:             concreteObj.ObjectMeta.UID,
   272  				ResourceVersion: concreteObj.ObjectMeta.ResourceVersion,
   273  				// We don't need to store labels nor annotations because
   274  				// they are not used by the CEP handlers.
   275  				Labels:      nil,
   276  				Annotations: nil,
   277  			},
   278  			Encryption: func() *cilium_v2.EncryptionSpec {
   279  				enc := concreteObj.Status.Encryption
   280  				return &enc
   281  			}(),
   282  			Identity:   concreteObj.Status.Identity,
   283  			Networking: concreteObj.Status.Networking,
   284  			NamedPorts: concreteObj.Status.NamedPorts,
   285  		}, nil
   286  	case *types.CiliumEndpoint:
   287  		return obj, nil
   288  	case cache.DeletedFinalStateUnknown:
   289  		if _, ok := concreteObj.Obj.(*types.CiliumEndpoint); ok {
   290  			return obj, nil
   291  		}
   292  		ciliumEndpoint, ok := concreteObj.Obj.(*cilium_v2.CiliumEndpoint)
   293  		if !ok {
   294  			return nil, fmt.Errorf("unknown object type %T", concreteObj.Obj)
   295  		}
   296  		return cache.DeletedFinalStateUnknown{
   297  			Key: concreteObj.Key,
   298  			Obj: &types.CiliumEndpoint{
   299  				TypeMeta: slim_metav1.TypeMeta{
   300  					Kind:       ciliumEndpoint.TypeMeta.Kind,
   301  					APIVersion: ciliumEndpoint.TypeMeta.APIVersion,
   302  				},
   303  				ObjectMeta: slim_metav1.ObjectMeta{
   304  					Name:            ciliumEndpoint.ObjectMeta.Name,
   305  					Namespace:       ciliumEndpoint.ObjectMeta.Namespace,
   306  					UID:             ciliumEndpoint.ObjectMeta.UID,
   307  					ResourceVersion: ciliumEndpoint.ObjectMeta.ResourceVersion,
   308  					// We don't need to store labels nor annotations because
   309  					// they are not used by the CEP handlers.
   310  					Labels:      nil,
   311  					Annotations: nil,
   312  				},
   313  				Encryption: func() *cilium_v2.EncryptionSpec {
   314  					enc := ciliumEndpoint.Status.Encryption
   315  					return &enc
   316  				}(),
   317  				Identity:   ciliumEndpoint.Status.Identity,
   318  				Networking: ciliumEndpoint.Status.Networking,
   319  				NamedPorts: ciliumEndpoint.Status.NamedPorts,
   320  			},
   321  		}, nil
   322  	default:
   323  		return nil, fmt.Errorf("unknown object type %T", concreteObj)
   324  	}
   325  }
   326  
   327  // ConvertCEPToCoreCEP converts a CiliumEndpoint to a CoreCiliumEndpoint
   328  // containing only a minimal set of entities used to
   329  func ConvertCEPToCoreCEP(cep *cilium_v2.CiliumEndpoint) *cilium_v2alpha1.CoreCiliumEndpoint {
   330  	// Copy Networking field into core CEP
   331  	var epNetworking *cilium_v2.EndpointNetworking
   332  	if cep.Status.Networking != nil {
   333  		epNetworking = new(cilium_v2.EndpointNetworking)
   334  		cep.Status.Networking.DeepCopyInto(epNetworking)
   335  	}
   336  	var identityID int64 = 0
   337  	if cep.Status.Identity != nil {
   338  		identityID = cep.Status.Identity.ID
   339  	}
   340  	return &cilium_v2alpha1.CoreCiliumEndpoint{
   341  		Name:       cep.GetName(),
   342  		Networking: epNetworking,
   343  		Encryption: cep.Status.Encryption,
   344  		IdentityID: identityID,
   345  		NamedPorts: cep.Status.NamedPorts.DeepCopy(),
   346  	}
   347  }
   348  
   349  // ConvertCoreCiliumEndpointToTypesCiliumEndpoint converts CoreCiliumEndpoint object to types.CiliumEndpoint.
   350  func ConvertCoreCiliumEndpointToTypesCiliumEndpoint(ccep *cilium_v2alpha1.CoreCiliumEndpoint, ns string) *types.CiliumEndpoint {
   351  	return &types.CiliumEndpoint{
   352  		ObjectMeta: slim_metav1.ObjectMeta{
   353  			Name:      ccep.Name,
   354  			Namespace: ns,
   355  		},
   356  		Encryption: func() *cilium_v2.EncryptionSpec {
   357  			enc := ccep.Encryption
   358  			return &enc
   359  		}(),
   360  		Identity: &cilium_v2.EndpointIdentity{
   361  			ID: ccep.IdentityID,
   362  		},
   363  		Networking: ccep.Networking,
   364  		NamedPorts: ccep.NamedPorts,
   365  	}
   366  }