github.com/cilium/cilium@v1.16.2/pkg/k8s/apis/cilium.io/client/register.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package client 5 6 import ( 7 "context" 8 _ "embed" 9 "fmt" 10 11 "golang.org/x/sync/errgroup" 12 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 13 apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" 14 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 15 "sigs.k8s.io/yaml" 16 17 k8sconst "github.com/cilium/cilium/pkg/k8s/apis/cilium.io" 18 k8sconstv2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" 19 k8sconstv2alpha1 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1" 20 "github.com/cilium/cilium/pkg/k8s/apis/crdhelpers" 21 "github.com/cilium/cilium/pkg/k8s/client" 22 "github.com/cilium/cilium/pkg/k8s/synced" 23 "github.com/cilium/cilium/pkg/logging" 24 "github.com/cilium/cilium/pkg/logging/logfields" 25 "github.com/cilium/cilium/pkg/versioncheck" 26 ) 27 28 const ( 29 // subsysK8s is the value for logfields.LogSubsys 30 subsysK8s = "k8s" 31 32 // CNPCRDName is the full name of the CNP CRD. 33 CNPCRDName = k8sconstv2.CNPKindDefinition + "/" + k8sconstv2.CustomResourceDefinitionVersion 34 35 // CCNPCRDName is the full name of the CCNP CRD. 36 CCNPCRDName = k8sconstv2.CCNPKindDefinition + "/" + k8sconstv2.CustomResourceDefinitionVersion 37 38 // CEPCRDName is the full name of the CEP CRD. 39 CEPCRDName = k8sconstv2.CEPKindDefinition + "/" + k8sconstv2.CustomResourceDefinitionVersion 40 41 // CIDCRDName is the full name of the CID CRD. 42 CIDCRDName = k8sconstv2.CIDKindDefinition + "/" + k8sconstv2.CustomResourceDefinitionVersion 43 44 // CNCRDName is the full name of the CN CRD. 45 CNCRDName = k8sconstv2.CNKindDefinition + "/" + k8sconstv2.CustomResourceDefinitionVersion 46 47 // CEWCRDName is the full name of the CEW CRD. 48 CEWCRDName = k8sconstv2.CEWKindDefinition + "/" + k8sconstv2.CustomResourceDefinitionVersion 49 50 // CLRPCRDName is the full name of the CLRP CRD. 51 CLRPCRDName = k8sconstv2.CLRPKindDefinition + "/" + k8sconstv2.CustomResourceDefinitionVersion 52 53 // CEGPCRDName is the full name of the CEGP CRD. 54 CEGPCRDName = k8sconstv2.CEGPKindDefinition + "/" + k8sconstv2.CustomResourceDefinitionVersion 55 56 // CESCRDName is the full name of the CES CRD. 57 CESCRDName = k8sconstv2alpha1.CESKindDefinition + "/" + k8sconstv2alpha1.CustomResourceDefinitionVersion 58 59 // CCECCRDName is the full name of the CCEC CRD. 60 CCECCRDName = k8sconstv2.CCECKindDefinition + "/" + k8sconstv2.CustomResourceDefinitionVersion 61 62 // CECCRDName is the full name of the CEC CRD. 63 CECCRDName = k8sconstv2.CECKindDefinition + "/" + k8sconstv2.CustomResourceDefinitionVersion 64 65 // CNCCRDName is the full name of the CiliumNodeConfig CRD. 66 CNCCRDName = k8sconstv2.CNCKindDefinition + "/" + k8sconstv2.CustomResourceDefinitionVersion 67 68 // BGPPCRDName is the full name of the BGPP CRD. 69 BGPPCRDName = k8sconstv2alpha1.BGPPKindDefinition + "/" + k8sconstv2alpha1.CustomResourceDefinitionVersion 70 71 // BGPClusterConfigCRDName is the full name of the BGP Cluster Config CRD. 72 BGPClusterConfigCRDName = k8sconstv2alpha1.BGPCCKindDefinition + "/" + k8sconstv2alpha1.CustomResourceDefinitionVersion 73 74 // BGPPeerConfigCRDName is the full name of the BGP PeerConfig CRD. 75 BGPPeerConfigCRDName = k8sconstv2alpha1.BGPPCKindDefinition + "/" + k8sconstv2alpha1.CustomResourceDefinitionVersion 76 77 // BGPAdvertisementCRDName is the full name of the BGP Advertisement CRD. 78 BGPAdvertisementCRDName = k8sconstv2alpha1.BGPAKindDefinition + "/" + k8sconstv2alpha1.CustomResourceDefinitionVersion 79 80 // BGPNodeConfigCRDName is the full name of the BGP Node Config CRD. 81 BGPNodeConfigCRDName = k8sconstv2alpha1.BGPNCKindDefinition + "/" + k8sconstv2alpha1.CustomResourceDefinitionVersion 82 83 // BGPNodeConfigOverrideCRDName is the full name of the BGP Node Config Override CRD. 84 BGPNodeConfigOverrideCRDName = k8sconstv2alpha1.BGPNCOKindDefinition + "/" + k8sconstv2alpha1.CustomResourceDefinitionVersion 85 86 // LBIPPoolCRDName is the full name of the BGPPool CRD. 87 LBIPPoolCRDName = k8sconstv2alpha1.PoolKindDefinition + "/" + k8sconstv2alpha1.CustomResourceDefinitionVersion 88 89 // CNCCRDNameAlpha is the full name of the CiliumNodeConfig CRD. 90 // TODO remove me when CNC CRD v2alpha1 will be deprecated. 91 CNCCRDNameAlpha = k8sconstv2alpha1.CNCKindDefinition + "/" + k8sconstv2alpha1.CustomResourceDefinitionVersion 92 93 // CCGCRDName is the full name of the CiliumCIDRGroup CRD. 94 CCGCRDName = k8sconstv2alpha1.CCGKindDefinition + "/" + k8sconstv2alpha1.CustomResourceDefinitionVersion 95 96 // L2AnnouncementCRDName is the full name of the CiliumL2AnnouncementPolicy CRD. 97 L2AnnouncementCRDName = k8sconstv2alpha1.L2AnnouncementKindDefinition + "/" + k8sconstv2alpha1.CustomResourceDefinitionVersion 98 99 // CPIPCRDName is the full name of the CiliumPodIPPool CRD. 100 CPIPCRDName = k8sconstv2alpha1.CPIPKindDefinition + "/" + k8sconstv2alpha1.CustomResourceDefinitionVersion 101 ) 102 103 // log is the k8s package logger object. 104 var log = logging.DefaultLogger.WithField(logfields.LogSubsys, subsysK8s) 105 106 type CRDList struct { 107 Name string 108 FullName string 109 } 110 111 // CustomResourceDefinitionList returns a map of CRDs 112 func CustomResourceDefinitionList() map[string]*CRDList { 113 return map[string]*CRDList{ 114 synced.CRDResourceName(k8sconstv2.CNPName): { 115 Name: CNPCRDName, 116 FullName: k8sconstv2.CNPName, 117 }, 118 synced.CRDResourceName(k8sconstv2.CCNPName): { 119 Name: CCNPCRDName, 120 FullName: k8sconstv2.CCNPName, 121 }, 122 synced.CRDResourceName(k8sconstv2.CNName): { 123 Name: CNCRDName, 124 FullName: k8sconstv2.CNName, 125 }, 126 synced.CRDResourceName(k8sconstv2.CIDName): { 127 Name: CIDCRDName, 128 FullName: k8sconstv2.CIDName, 129 }, 130 synced.CRDResourceName(k8sconstv2.CEPName): { 131 Name: CEPCRDName, 132 FullName: k8sconstv2.CEPName, 133 }, 134 synced.CRDResourceName(k8sconstv2.CEWName): { 135 Name: CEWCRDName, 136 FullName: k8sconstv2.CEWName, 137 }, 138 synced.CRDResourceName(k8sconstv2.CLRPName): { 139 Name: CLRPCRDName, 140 FullName: k8sconstv2.CLRPName, 141 }, 142 synced.CRDResourceName(k8sconstv2.CEGPName): { 143 Name: CEGPCRDName, 144 FullName: k8sconstv2.CEGPName, 145 }, 146 synced.CRDResourceName(k8sconstv2.CNCName): { 147 Name: CNCCRDName, 148 FullName: k8sconstv2.CNCName, 149 }, 150 synced.CRDResourceName(k8sconstv2alpha1.CESName): { 151 Name: CESCRDName, 152 FullName: k8sconstv2alpha1.CESName, 153 }, 154 synced.CRDResourceName(k8sconstv2.CCECName): { 155 Name: CCECCRDName, 156 FullName: k8sconstv2.CCECName, 157 }, 158 synced.CRDResourceName(k8sconstv2.CECName): { 159 Name: CECCRDName, 160 FullName: k8sconstv2.CECName, 161 }, 162 synced.CRDResourceName(k8sconstv2alpha1.BGPPName): { 163 Name: BGPPCRDName, 164 FullName: k8sconstv2alpha1.BGPPName, 165 }, 166 synced.CRDResourceName(k8sconstv2alpha1.BGPCCName): { 167 Name: BGPClusterConfigCRDName, 168 FullName: k8sconstv2alpha1.BGPCCName, 169 }, 170 synced.CRDResourceName(k8sconstv2alpha1.BGPPCName): { 171 Name: BGPPeerConfigCRDName, 172 FullName: k8sconstv2alpha1.BGPPCName, 173 }, 174 synced.CRDResourceName(k8sconstv2alpha1.BGPAName): { 175 Name: BGPAdvertisementCRDName, 176 FullName: k8sconstv2alpha1.BGPAName, 177 }, 178 synced.CRDResourceName(k8sconstv2alpha1.BGPNCName): { 179 Name: BGPNodeConfigCRDName, 180 FullName: k8sconstv2alpha1.BGPNCName, 181 }, 182 synced.CRDResourceName(k8sconstv2alpha1.BGPNCOName): { 183 Name: BGPNodeConfigOverrideCRDName, 184 FullName: k8sconstv2alpha1.BGPNCOName, 185 }, 186 synced.CRDResourceName(k8sconstv2alpha1.LBIPPoolName): { 187 Name: LBIPPoolCRDName, 188 FullName: k8sconstv2alpha1.LBIPPoolName, 189 }, 190 // TODO remove me when CNC v2alpha 1 will be deprecated 191 synced.CRDResourceName(k8sconstv2alpha1.CNCName): { 192 Name: CNCCRDNameAlpha, 193 FullName: k8sconstv2alpha1.CNCName, 194 }, 195 synced.CRDResourceName(k8sconstv2alpha1.CCGName): { 196 Name: CCGCRDName, 197 FullName: k8sconstv2alpha1.CCGName, 198 }, 199 synced.CRDResourceName(k8sconstv2alpha1.L2AnnouncementName): { 200 Name: L2AnnouncementCRDName, 201 FullName: k8sconstv2alpha1.L2AnnouncementName, 202 }, 203 synced.CRDResourceName(k8sconstv2alpha1.CPIPName): { 204 Name: CPIPCRDName, 205 FullName: k8sconstv2alpha1.CPIPName, 206 }, 207 } 208 } 209 210 // CreateCustomResourceDefinitions creates our CRD objects in the Kubernetes 211 // cluster. 212 func CreateCustomResourceDefinitions(clientset apiextensionsclient.Interface) error { 213 g, _ := errgroup.WithContext(context.Background()) 214 215 crds := CustomResourceDefinitionList() 216 217 for _, r := range synced.AllCiliumCRDResourceNames() { 218 if crd, ok := crds[r]; ok { 219 g.Go(func() error { 220 return createCRD(crd.Name, crd.FullName)(clientset) 221 }) 222 } else { 223 log.Fatalf("Unknown resource %s. Please update pkg/k8s/apis/cilium.io/client to understand this type.", r) 224 } 225 } 226 227 return g.Wait() 228 } 229 230 var ( 231 //go:embed crds/v2/ciliumnetworkpolicies.yaml 232 crdsCiliumnetworkpolicies []byte 233 234 //go:embed crds/v2/ciliumclusterwidenetworkpolicies.yaml 235 crdsCiliumclusterwidenetworkpolicies []byte 236 237 //go:embed crds/v2/ciliumendpoints.yaml 238 crdsCiliumendpoints []byte 239 240 //go:embed crds/v2/ciliumidentities.yaml 241 crdsCiliumidentities []byte 242 243 //go:embed crds/v2/ciliumnodes.yaml 244 crdsCiliumnodes []byte 245 246 //go:embed crds/v2/ciliumexternalworkloads.yaml 247 crdsCiliumexternalworkloads []byte 248 249 //go:embed crds/v2/ciliumlocalredirectpolicies.yaml 250 crdsCiliumlocalredirectpolicies []byte 251 252 //go:embed crds/v2/ciliumegressgatewaypolicies.yaml 253 crdsv2Ciliumegressgatewaypolicies []byte 254 255 //go:embed crds/v2/ciliumnodeconfigs.yaml 256 crdsv2CiliumNodeConfigs []byte 257 258 //go:embed crds/v2alpha1/ciliumendpointslices.yaml 259 crdsv2Alpha1Ciliumendpointslices []byte 260 261 //go:embed crds/v2/ciliumclusterwideenvoyconfigs.yaml 262 crdsv2Ciliumclusterwideenvoyconfigs []byte 263 264 //go:embed crds/v2/ciliumenvoyconfigs.yaml 265 crdsv2Ciliumenvoyconfigs []byte 266 267 //go:embed crds/v2alpha1/ciliumbgppeeringpolicies.yaml 268 crdsv2Alpha1Ciliumbgppeeringpolicies []byte 269 270 //go:embed crds/v2alpha1/ciliumbgpclusterconfigs.yaml 271 crdsv2Alpha1Ciliumbgpclusterconfigs []byte 272 273 //go:embed crds/v2alpha1/ciliumbgppeerconfigs.yaml 274 crdsv2Alpha1Ciliumbgppeerconfigs []byte 275 276 //go:embed crds/v2alpha1/ciliumbgpadvertisements.yaml 277 crdsv2Alpha1Ciliumbgpadvertisements []byte 278 279 //go:embed crds/v2alpha1/ciliumbgpnodeconfigs.yaml 280 crdsv2Alpha1Ciliumbgpnodeconfigs []byte 281 282 //go:embed crds/v2alpha1/ciliumbgpnodeconfigoverrides.yaml 283 crdsv2Alpha1Ciliumbgpnodeconfigoverrides []byte 284 285 //go:embed crds/v2alpha1/ciliumloadbalancerippools.yaml 286 crdsv2Alpha1Ciliumloadbalancerippools []byte 287 288 //go:embed crds/v2alpha1/ciliumcidrgroups.yaml 289 crdsv2Alpha1CiliumCIDRGroups []byte 290 291 //go:embed crds/v2alpha1/ciliuml2announcementpolicies.yaml 292 crdsv2Alpha1CiliumL2AnnouncementPolicies []byte 293 294 //go:embed crds/v2alpha1/ciliumpodippools.yaml 295 crdsv2Alpha1CiliumPodIPPools []byte 296 ) 297 298 // GetPregeneratedCRD returns the pregenerated CRD based on the requested CRD 299 // name. The pregenerated CRDs are generated by the controller-gen tool and 300 // serialized into binary form by go-bindata. This function retrieves CRDs from 301 // the binary form. 302 func GetPregeneratedCRD(crdName string) apiextensionsv1.CustomResourceDefinition { 303 var ( 304 err error 305 crdBytes []byte 306 ) 307 308 scopedLog := log.WithField("crdName", crdName) 309 310 switch crdName { 311 case CNPCRDName: 312 crdBytes = crdsCiliumnetworkpolicies 313 case CCNPCRDName: 314 crdBytes = crdsCiliumclusterwidenetworkpolicies 315 case CEPCRDName: 316 crdBytes = crdsCiliumendpoints 317 case CIDCRDName: 318 crdBytes = crdsCiliumidentities 319 case CNCRDName: 320 crdBytes = crdsCiliumnodes 321 case CEWCRDName: 322 crdBytes = crdsCiliumexternalworkloads 323 case CLRPCRDName: 324 crdBytes = crdsCiliumlocalredirectpolicies 325 case CEGPCRDName: 326 crdBytes = crdsv2Ciliumegressgatewaypolicies 327 case CESCRDName: 328 crdBytes = crdsv2Alpha1Ciliumendpointslices 329 case CCECCRDName: 330 crdBytes = crdsv2Ciliumclusterwideenvoyconfigs 331 case CECCRDName: 332 crdBytes = crdsv2Ciliumenvoyconfigs 333 case BGPPCRDName: 334 crdBytes = crdsv2Alpha1Ciliumbgppeeringpolicies 335 case BGPClusterConfigCRDName: 336 crdBytes = crdsv2Alpha1Ciliumbgpclusterconfigs 337 case BGPPeerConfigCRDName: 338 crdBytes = crdsv2Alpha1Ciliumbgppeerconfigs 339 case BGPAdvertisementCRDName: 340 crdBytes = crdsv2Alpha1Ciliumbgpadvertisements 341 case BGPNodeConfigCRDName: 342 crdBytes = crdsv2Alpha1Ciliumbgpnodeconfigs 343 case BGPNodeConfigOverrideCRDName: 344 crdBytes = crdsv2Alpha1Ciliumbgpnodeconfigoverrides 345 case LBIPPoolCRDName: 346 crdBytes = crdsv2Alpha1Ciliumloadbalancerippools 347 case CNCCRDNameAlpha: 348 crdBytes = crdsv2CiliumNodeConfigs 349 case CNCCRDName: 350 crdBytes = crdsv2CiliumNodeConfigs 351 case CCGCRDName: 352 crdBytes = crdsv2Alpha1CiliumCIDRGroups 353 case L2AnnouncementCRDName: 354 crdBytes = crdsv2Alpha1CiliumL2AnnouncementPolicies 355 case CPIPCRDName: 356 crdBytes = crdsv2Alpha1CiliumPodIPPools 357 default: 358 scopedLog.Fatal("Pregenerated CRD does not exist") 359 } 360 361 ciliumCRD := apiextensionsv1.CustomResourceDefinition{} 362 err = yaml.Unmarshal(crdBytes, &ciliumCRD) 363 if err != nil { 364 scopedLog.WithError(err).Fatal("Error unmarshalling pregenerated CRD") 365 } 366 367 return ciliumCRD 368 } 369 370 // createCRD creates and updates a CRD. 371 // It should be called on agent startup but is idempotent and safe to call again. 372 func createCRD(crdVersionedName string, crdMetaName string) func(clientset apiextensionsclient.Interface) error { 373 return func(clientset apiextensionsclient.Interface) error { 374 ciliumCRD := GetPregeneratedCRD(crdVersionedName) 375 376 return crdhelpers.CreateUpdateCRD( 377 clientset, 378 constructV1CRD(crdMetaName, ciliumCRD), 379 crdhelpers.NewDefaultPoller(), 380 k8sconst.CustomResourceDefinitionSchemaVersionKey, 381 versioncheck.MustVersion(k8sconst.CustomResourceDefinitionSchemaVersion), 382 ) 383 } 384 } 385 386 func constructV1CRD( 387 name string, 388 template apiextensionsv1.CustomResourceDefinition, 389 ) *apiextensionsv1.CustomResourceDefinition { 390 return &apiextensionsv1.CustomResourceDefinition{ 391 ObjectMeta: metav1.ObjectMeta{ 392 Name: name, 393 Labels: map[string]string{ 394 k8sconst.CustomResourceDefinitionSchemaVersionKey: k8sconst.CustomResourceDefinitionSchemaVersion, 395 }, 396 }, 397 Spec: apiextensionsv1.CustomResourceDefinitionSpec{ 398 Group: k8sconst.CustomResourceDefinitionGroup, 399 Names: apiextensionsv1.CustomResourceDefinitionNames{ 400 Kind: template.Spec.Names.Kind, 401 Plural: template.Spec.Names.Plural, 402 ShortNames: template.Spec.Names.ShortNames, 403 Singular: template.Spec.Names.Singular, 404 Categories: template.Spec.Names.Categories, 405 }, 406 Scope: template.Spec.Scope, 407 Versions: template.Spec.Versions, 408 Conversion: template.Spec.Conversion, // conversion strategy is needed to support several versions of a same CRD 409 }, 410 } 411 } 412 413 // RegisterCRDs registers all CRDs with the K8s apiserver. 414 func RegisterCRDs(clientset client.Clientset) error { 415 if err := CreateCustomResourceDefinitions(clientset); err != nil { 416 return fmt.Errorf("Unable to create custom resource definition: %w", err) 417 } 418 419 return nil 420 }