github.com/cilium/cilium@v1.16.2/pkg/clustermesh/mcsapi/cell.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package mcsapi 5 6 import ( 7 "context" 8 "errors" 9 "fmt" 10 11 "github.com/cilium/hive/cell" 12 "github.com/sirupsen/logrus" 13 "github.com/spf13/pflag" 14 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 15 "k8s.io/apimachinery/pkg/runtime" 16 "k8s.io/apimachinery/pkg/runtime/schema" 17 ctrlRuntime "sigs.k8s.io/controller-runtime" 18 mcsapiv1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1" 19 mcsapicontrollers "sigs.k8s.io/mcs-api/pkg/controllers" 20 21 "github.com/cilium/cilium/pkg/clustermesh/common" 22 "github.com/cilium/cilium/pkg/clustermesh/types" 23 k8sClient "github.com/cilium/cilium/pkg/k8s/client" 24 ) 25 26 var Cell = cell.Module( 27 "mcsapi", 28 "Multi-Cluster Services API", 29 cell.Config(MCSAPIConfig{}), 30 cell.Invoke(initMCSAPIController), 31 ) 32 33 type mcsAPIParams struct { 34 cell.In 35 36 common.Config 37 Cfg MCSAPIConfig 38 39 // ClusterInfo is the id/name of the local cluster. 40 ClusterInfo types.ClusterInfo 41 42 Clientset k8sClient.Clientset 43 CtrlRuntimeManager ctrlRuntime.Manager 44 Scheme *runtime.Scheme 45 46 Logger logrus.FieldLogger 47 } 48 49 type MCSAPIConfig struct { 50 // ClusterMeshEnableEndpointSync enables the MCS API support 51 ClusterMeshEnableMCSAPI bool `mapstructure:"clustermesh-enable-mcs-api"` 52 } 53 54 // Flags adds the flags used by ClientConfig. 55 func (cfg MCSAPIConfig) Flags(flags *pflag.FlagSet) { 56 flags.BoolVar(&cfg.ClusterMeshEnableMCSAPI, 57 "clustermesh-enable-mcs-api", 58 false, 59 "Whether or not the MCS API support is enabled.", 60 ) 61 } 62 63 var requiredGVK = []schema.GroupVersionKind{ 64 mcsapiv1alpha1.SchemeGroupVersion.WithKind("serviceimports"), 65 mcsapiv1alpha1.SchemeGroupVersion.WithKind("serviceexports"), 66 } 67 68 func checkCRD(ctx context.Context, clientset k8sClient.Clientset, gvk schema.GroupVersionKind) error { 69 if !clientset.IsEnabled() { 70 return nil 71 } 72 73 crd, err := clientset.ApiextensionsV1().CustomResourceDefinitions().Get(ctx, gvk.GroupKind().String(), metav1.GetOptions{}) 74 if err != nil { 75 return err 76 } 77 78 found := false 79 for _, v := range crd.Spec.Versions { 80 if v.Name == gvk.Version { 81 found = true 82 break 83 } 84 } 85 if !found { 86 return fmt.Errorf("CRD %q does not have version %q", gvk.GroupKind().String(), gvk.Version) 87 } 88 89 return nil 90 } 91 92 func checkRequiredCRDs(ctx context.Context, clientset k8sClient.Clientset) error { 93 var res error 94 for _, gvk := range requiredGVK { 95 if err := checkCRD(ctx, clientset, gvk); err != nil { 96 res = errors.Join(res, err) 97 } 98 } 99 return res 100 } 101 102 func initMCSAPIController(params mcsAPIParams) error { 103 if !params.Clientset.IsEnabled() || params.ClusterMeshConfig == "" || !params.Cfg.ClusterMeshEnableMCSAPI { 104 return nil 105 } 106 107 params.Logger.WithField("requiredGVK", requiredGVK).Info("Checking for required MCS-API resources") 108 if err := checkRequiredCRDs(context.Background(), params.Clientset); err != nil { 109 params.Logger.WithError(err).Error("Required MCS-API resources are not found, please refer to docs for installation instructions") 110 return err 111 } 112 if err := mcsapiv1alpha1.AddToScheme(params.Scheme); err != nil { 113 return err 114 } 115 116 if err := newMCSAPIServiceReconciler(params.CtrlRuntimeManager, params.Logger, params.ClusterInfo.Name).SetupWithManager(params.CtrlRuntimeManager); err != nil { 117 return fmt.Errorf("Failed to register MCSAPIServiceReconciler: %w", err) 118 } 119 120 // Upstream controller that we use as is to update the ServiceImport 121 // objects with the IPs of the derived Services. 122 svcReconciler := mcsapicontrollers.ServiceReconciler{ 123 Client: params.CtrlRuntimeManager.GetClient(), 124 Log: params.CtrlRuntimeManager.GetLogger(), 125 } 126 if err := svcReconciler.SetupWithManager(params.CtrlRuntimeManager); err != nil { 127 return fmt.Errorf("Failed to register mcsapicontrollers.ServiceReconciler: %w", err) 128 } 129 130 params.Logger.Info("Multi-Cluster Services API support enabled") 131 return nil 132 }