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 }