@@ -17,27 +17,69 @@ limitations under the License.
1717package main
1818
1919import (
20+ "context"
2021 "flag"
22+ "fmt"
2123 "os"
2224 "time"
2325
26+ "github.com/go-logr/logr"
27+ admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
28+ "k8s.io/apimachinery/pkg/types"
2429 ctrl "sigs.k8s.io/controller-runtime"
30+ "sigs.k8s.io/controller-runtime/pkg/client"
2531 "sigs.k8s.io/controller-runtime/pkg/healthz"
2632 "sigs.k8s.io/controller-runtime/pkg/log/zap"
33+ "sigs.k8s.io/controller-runtime/pkg/webhook"
2734
2835 "github.com/StarRocks/starrocks-kubernetes-operator/cmd/config"
2936 srapi "github.com/StarRocks/starrocks-kubernetes-operator/pkg/apis/starrocks/v1"
3037 "github.com/StarRocks/starrocks-kubernetes-operator/pkg/controllers"
3138 "github.com/StarRocks/starrocks-kubernetes-operator/pkg/k8sutils"
39+ srwebhook "github.com/StarRocks/starrocks-kubernetes-operator/pkg/webhook"
3240)
3341
3442var (
3543 _metricsAddr string
3644 _enableLeaderElection bool
3745 _probeAddr string
3846 _namespace string
47+ _enableWebhooks bool
3948)
4049
50+ // caBundleUpdater updates the ValidatingAdmissionWebhook with CA bundle after manager starts
51+ type caBundleUpdater struct {
52+ client client.Client
53+ caCert []byte
54+ logger logr.Logger
55+ }
56+
57+ // Start implements the Runnable interface
58+ func (c * caBundleUpdater ) Start (ctx context.Context ) error {
59+ c .logger .Info ("updating webhook CA bundle" )
60+
61+ webhookName := "starrockscluster-validating-webhook"
62+
63+ // Get the existing ValidatingAdmissionWebhook
64+ webhook := & admissionregistrationv1.ValidatingWebhookConfiguration {}
65+ if err := c .client .Get (ctx , types.NamespacedName {Name : webhookName }, webhook ); err != nil {
66+ return fmt .Errorf ("failed to get ValidatingAdmissionWebhook: %v" , err )
67+ }
68+
69+ // Update caBundle for all webhooks
70+ for i := range webhook .Webhooks {
71+ webhook .Webhooks [i ].ClientConfig .CABundle = c .caCert
72+ }
73+
74+ // Update the webhook configuration
75+ if err := c .client .Update (ctx , webhook ); err != nil {
76+ return fmt .Errorf ("failed to update ValidatingAdmissionWebhook: %v" , err )
77+ }
78+
79+ c .logger .Info ("webhook CA bundle updated successfully" )
80+ return nil
81+ }
82+
4183func main () {
4284 flag .StringVar (& _metricsAddr , "metrics-bind-address" , ":8080" , "The address the metric endpoint binds to." )
4385 flag .StringVar (& _probeAddr , "health-probe-bind-address" , ":8081" , "The address the probe endpoint binds to." )
@@ -48,6 +90,10 @@ func main() {
4890 "restricts the manager's cache to watch objects in the desired namespace. Defaults to all namespaces." )
4991 flag .StringVar (& config .DNSDomainSuffix , "dns-domain-suffix" , "cluster.local" , "The suffix of the dns domain in k8s" )
5092 flag .BoolVar (& config .VolumeNameWithHash , "volume-name-with-hash" , true , "Add a hash to the volume name" )
93+ flag .BoolVar (& _enableWebhooks , "enable-webhooks" , false , "Enable admission webhooks. " +
94+ "Requires TLS certificates to be configured. Disabled by default for local development." )
95+ flag .IntVar (& config .WebhookCertValidityDays , "webhook-cert-validity-days" , 365 ,
96+ "Validity period in days for self-signed webhook certificates" )
5197
5298 // Set up logger.
5399 opts := zap.Options {}
@@ -86,6 +132,41 @@ func main() {
86132 os .Exit (1 )
87133 }
88134
135+ // setup webhooks if enabled
136+ if _enableWebhooks {
137+ // Get webhook configuration from environment variables
138+ webhookNamespace := os .Getenv ("WEBHOOK_NAMESPACE" )
139+ webhookServiceName := os .Getenv ("WEBHOOK_SERVICE_NAME" )
140+ webhookCertDir := os .Getenv ("WEBHOOK_CERT_DIR" )
141+
142+ // Generate self-signed certificates if not provided
143+ caCert , err := srwebhook .GenerateSelfSignedCerts (webhookCertDir , webhookServiceName , webhookNamespace , config .WebhookCertValidityDays )
144+ if err != nil {
145+ logger .Error (err , "unable to generate self-signed certificates" )
146+ os .Exit (1 )
147+ }
148+ logger .Info ("self-signed certificates generated for webhook server" , "validityDays" ,
149+ config .WebhookCertValidityDays , "namespace" , webhookNamespace , "serviceName" , webhookServiceName , "certDir" , webhookCertDir )
150+
151+ // Add CA bundle updater as a runnable that starts after the manager cache is ready
152+ if err := mgr .Add (& caBundleUpdater {
153+ client : mgr .GetClient (),
154+ caCert : caCert ,
155+ logger : logger .WithName ("ca-bundle-updater" ),
156+ }); err != nil {
157+ logger .Error (err , "unable to add CA bundle updater" )
158+ os .Exit (1 )
159+ }
160+
161+ if err := setupWebhooks (mgr ); err != nil {
162+ logger .Error (err , "unable to set up webhooks" )
163+ os .Exit (1 )
164+ }
165+ logger .Info ("webhooks enabled" )
166+ } else {
167+ logger .Info ("webhooks disabled - use --enable-webhooks to enable" )
168+ }
169+
89170 // +kubebuilder:scaffold:builder
90171
91172 if err := mgr .AddHealthzCheck ("healthz" , healthz .Ping ); err != nil {
@@ -107,3 +188,22 @@ func main() {
107188 os .Exit (1 )
108189 }
109190}
191+
192+ // setupWebhooks sets up webhooks for the manager
193+ func setupWebhooks (mgr ctrl.Manager ) error {
194+ // Set up the webhook server
195+ hookServer := mgr .GetWebhookServer ()
196+ if hookServer == nil {
197+ return fmt .Errorf ("failed to get webhook server from manager" )
198+ }
199+
200+ // Register the StarRocksCluster validating webhook
201+ validator := & srwebhook.StarRocksClusterValidator {
202+ Client : mgr .GetClient (),
203+ }
204+
205+ hookServer .Register ("/validate-starrocks-com-v1-starrockscluster" ,
206+ & webhook.Admission {Handler : validator })
207+
208+ return nil
209+ }
0 commit comments