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  }