github.com/ironcore-dev/gardener-extension-provider-ironcore@v0.3.2-0.20240314231816-8336447fb9a0/cmd/gardener-extension-admission-ironcore/app/app.go (about) 1 // SPDX-FileCopyrightText: 2022 SAP SE or an SAP affiliate company and IronCore contributors 2 // SPDX-License-Identifier: Apache-2.0 3 4 package app 5 6 import ( 7 "context" 8 "fmt" 9 "os" 10 11 controllercmd "github.com/gardener/gardener/extensions/pkg/controller/cmd" 12 "github.com/gardener/gardener/extensions/pkg/util" 13 webhookcmd "github.com/gardener/gardener/extensions/pkg/webhook/cmd" 14 "github.com/gardener/gardener/pkg/apis/core/install" 15 v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants" 16 gardenerhealthz "github.com/gardener/gardener/pkg/healthz" 17 "github.com/spf13/cobra" 18 corev1 "k8s.io/api/core/v1" 19 "k8s.io/client-go/rest" 20 "k8s.io/client-go/tools/clientcmd" 21 componentbaseconfig "k8s.io/component-base/config" 22 "k8s.io/component-base/version/verflag" 23 "sigs.k8s.io/controller-runtime/pkg/cache" 24 "sigs.k8s.io/controller-runtime/pkg/client" 25 "sigs.k8s.io/controller-runtime/pkg/cluster" 26 "sigs.k8s.io/controller-runtime/pkg/healthz" 27 logf "sigs.k8s.io/controller-runtime/pkg/log" 28 "sigs.k8s.io/controller-runtime/pkg/manager" 29 30 admissioncmd "github.com/ironcore-dev/gardener-extension-provider-ironcore/pkg/admission/cmd" 31 ironcoreinstall "github.com/ironcore-dev/gardener-extension-provider-ironcore/pkg/apis/ironcore/install" 32 providerironcore "github.com/ironcore-dev/gardener-extension-provider-ironcore/pkg/ironcore" 33 ) 34 35 // AdmissionName is the name of the admission component. 36 const AdmissionName = "admission-ironcore" 37 38 var log = logf.Log.WithName("gardener-extension-admission-ironcore") 39 40 // NewAdmissionCommand creates a new command for running an ironcore gardener-extension-admission-ironcore webhook. 41 func NewAdmissionCommand(ctx context.Context) *cobra.Command { 42 var ( 43 restOpts = &controllercmd.RESTOptions{} 44 mgrOpts = &controllercmd.ManagerOptions{ 45 LeaderElection: true, 46 LeaderElectionID: controllercmd.LeaderElectionNameID(AdmissionName), 47 LeaderElectionNamespace: os.Getenv("LEADER_ELECTION_NAMESPACE"), 48 WebhookServerPort: 443, 49 MetricsBindAddress: ":8080", 50 HealthBindAddress: ":8081", 51 WebhookCertDir: "/tmp/admission-aws-cert", 52 } 53 // options for the webhook server 54 webhookServerOptions = &webhookcmd.ServerOptions{ 55 Namespace: os.Getenv("WEBHOOK_CONFIG_NAMESPACE"), 56 } 57 webhookSwitches = admissioncmd.GardenWebhookSwitchOptions() 58 webhookOptions = webhookcmd.NewAddToManagerOptions( 59 AdmissionName, 60 "", 61 nil, 62 webhookServerOptions, 63 webhookSwitches, 64 ) 65 66 aggOption = controllercmd.NewOptionAggregator( 67 restOpts, 68 mgrOpts, 69 webhookOptions, 70 ) 71 ) 72 73 cmd := &cobra.Command{ 74 Use: fmt.Sprintf("admission-%s", providerironcore.Type), 75 76 RunE: func(cmd *cobra.Command, args []string) error { 77 verflag.PrintAndExitIfRequested() 78 79 if err := aggOption.Complete(); err != nil { 80 return fmt.Errorf("error completing options: %v", err) 81 } 82 83 util.ApplyClientConnectionConfigurationToRESTConfig(&componentbaseconfig.ClientConnectionConfiguration{ 84 QPS: 100.0, 85 Burst: 130, 86 }, restOpts.Completed().Config) 87 88 managerOptions := mgrOpts.Completed().Options() 89 90 // Operators can enable the source cluster option via SOURCE_CLUSTER environment variable. 91 // In-cluster config will be used if no SOURCE_KUBECONFIG is specified. 92 // 93 // The source cluster is for instance used by Gardener's certificate controller, to maintain certificate 94 // secrets in a different cluster ('runtime-garden') than the cluster where the webhook configurations 95 // are maintained ('virtual-garden'). 96 var sourceClusterConfig *rest.Config 97 if sourceClusterEnabled := os.Getenv("SOURCE_CLUSTER"); sourceClusterEnabled != "" { 98 log.Info("Configuring source cluster option") 99 var err error 100 sourceClusterConfig, err = clientcmd.BuildConfigFromFlags("", os.Getenv("SOURCE_KUBECONFIG")) 101 if err != nil { 102 return err 103 } 104 managerOptions.LeaderElectionConfig = sourceClusterConfig 105 } else { 106 // Restrict the cache for secrets to the configured namespace to avoid the need for cluster-wide list/watch permissions. 107 managerOptions.Cache = cache.Options{ 108 ByObject: map[client.Object]cache.ByObject{ 109 &corev1.Secret{}: {Namespaces: map[string]cache.Config{webhookOptions.Server.Completed().Namespace: {}}}, 110 }, 111 } 112 } 113 114 mgr, err := manager.New(restOpts.Completed().Config, mgrOpts.Completed().Options()) 115 if err != nil { 116 return fmt.Errorf("could not instantiate manager: %v", err) 117 } 118 119 install.Install(mgr.GetScheme()) 120 121 if err := ironcoreinstall.AddToScheme(mgr.GetScheme()); err != nil { 122 return fmt.Errorf("could not update manager scheme: %v", err) 123 } 124 125 var sourceCluster cluster.Cluster 126 if sourceClusterConfig != nil { 127 sourceCluster, err = cluster.New(sourceClusterConfig, func(opts *cluster.Options) { 128 opts.Logger = log 129 opts.Cache.DefaultNamespaces = map[string]cache.Config{v1beta1constants.GardenNamespace: {}} 130 }) 131 if err != nil { 132 return err 133 } 134 135 if err := mgr.AddReadyzCheck("source-informer-sync", gardenerhealthz.NewCacheSyncHealthz(sourceCluster.GetCache())); err != nil { 136 return err 137 } 138 139 if err = mgr.Add(sourceCluster); err != nil { 140 return err 141 } 142 } 143 144 log.Info("Setting up webhook server") 145 if _, err := webhookOptions.Completed().AddToManager(ctx, mgr, sourceCluster); err != nil { 146 return err 147 } 148 149 if err := mgr.AddReadyzCheck("informer-sync", gardenerhealthz.NewCacheSyncHealthz(mgr.GetCache())); err != nil { 150 return fmt.Errorf("could not add readycheck for informers: %w", err) 151 } 152 153 if err := mgr.AddHealthzCheck("ping", healthz.Ping); err != nil { 154 return fmt.Errorf("could not add healthcheck: %w", err) 155 } 156 157 if err := mgr.AddReadyzCheck("webhook-server", mgr.GetWebhookServer().StartedChecker()); err != nil { 158 return fmt.Errorf("could not add readycheck of webhook to manager: %w", err) 159 } 160 161 return mgr.Start(ctx) 162 }, 163 } 164 165 verflag.AddFlags(cmd.Flags()) 166 aggOption.AddFlags(cmd.Flags()) 167 168 return cmd 169 }