@@ -3,6 +3,7 @@ package injector
33import (
44 "context"
55 "crypto/tls"
6+ "fmt"
67 "net/http"
78 "os"
89 "time"
@@ -14,6 +15,7 @@ import (
1415 "github.com/numberly/vault-db-injector/pkg/k8smutator"
1516 "github.com/numberly/vault-db-injector/pkg/logger"
1617 promInjector "github.com/numberly/vault-db-injector/pkg/prometheus"
18+ "github.com/numberly/vault-db-injector/pkg/sentry"
1719 "github.com/prometheus/client_golang/prometheus"
1820 "github.com/prometheus/client_golang/prometheus/promhttp"
1921 kwhhttp "github.com/slok/kubewebhook/v2/pkg/http"
@@ -34,14 +36,16 @@ type starterImpl struct {
3436 errChan chan <- error
3537 successChan chan <- bool
3638 log logger.Logger
39+ sentry sentry.SentryService
3740}
3841
39- func NewWebhookStartor (cfg * config.Config , errChan chan <- error , successChan chan <- bool ) Startor {
42+ func NewWebhookStartor (cfg * config.Config , errChan chan <- error , successChan chan <- bool , sentrySvc sentry. SentryService ) Startor {
4043 return & starterImpl {
4144 cfg : cfg ,
4245 errChan : errChan ,
4346 successChan : successChan ,
4447 log : logger .GetLogger (),
48+ sentry : sentrySvc ,
4549 }
4650}
4751
@@ -58,6 +62,7 @@ func (s *starterImpl) StartWebhook(ctx context.Context, stopChan chan struct{})
5862 metricsRec , err := kwhprometheus .NewRecorder (kwhprometheus.RecorderConfig {Registry : reg })
5963 if err != nil {
6064 close (stopChan )
65+ s .sentry .CaptureError (err )
6166 s .log .Fatalf ("could not create Prometheus metrics recorder: %v" , err )
6267 }
6368
@@ -70,23 +75,27 @@ func (s *starterImpl) StartWebhook(ctx context.Context, stopChan chan struct{})
7075 wh , err := kwhmutating .NewWebhook (mcfg )
7176 if err != nil {
7277 close (stopChan )
78+ s .sentry .CaptureError (err )
7379 return errors .Newf ("error creating webhook: %w" , err )
7480 }
7581
7682 serverCert , err := tls .LoadX509KeyPair (s .cfg .CertFile , s .cfg .KeyFile )
7783 if err != nil {
7884 close (stopChan )
85+ s .sentry .CaptureError (err )
7986 s .log .Fatalf ("Failed to load server certificate: %v" , err )
8087 }
8188
8289 caCertPool , err := k8sClient .GetKubernetesCACert ()
8390 if err != nil {
8491 close (stopChan )
92+ s .sentry .CaptureError (err )
8593 s .log .Fatalf ("Failed to get Kubernetes CA certificate: %v" , err )
8694 }
8795
8896 certByte , err := os .ReadFile (s .cfg .CertFile )
8997 if err != nil {
98+ s .sentry .CaptureError (err )
9099 logger .Errorf (err .Error ())
91100 }
92101 caCertPool .AppendCertsFromPEM (certByte )
@@ -98,9 +107,13 @@ func (s *starterImpl) StartWebhook(ctx context.Context, stopChan chan struct{})
98107 })
99108 if err != nil {
100109 close (stopChan )
110+ s .sentry .CaptureError (err )
101111 return errors .Newf ("error creating webhook handler: %w" , err )
102112 }
103113
114+ // Add Sentry recovery middleware
115+ wrappedHandler := SentryRecoveryMiddleware (s .sentry )(whHandler )
116+
104117 // Configurer mTLS
105118 tlsConfig := & tls.Config {
106119 Certificates : []tls.Certificate {serverCert },
@@ -112,7 +125,7 @@ func (s *starterImpl) StartWebhook(ctx context.Context, stopChan chan struct{})
112125 ReadTimeout : 10 * time .Second ,
113126 WriteTimeout : 10 * time .Second ,
114127 TLSConfig : tlsConfig ,
115- Handler : whHandler ,
128+ Handler : wrappedHandler ,
116129 }
117130
118131 s .successChan <- true
@@ -123,6 +136,7 @@ func (s *starterImpl) StartWebhook(ctx context.Context, stopChan chan struct{})
123136 logger .Infof ("Listening on :8443" )
124137 err = httpServer .ListenAndServeTLS ("" , "" )
125138 if err != nil {
139+ s .sentry .CaptureError (err )
126140 errCh <- errors .Newf ("error serving webhook: %w" , err )
127141 close (stopChan )
128142 }
@@ -134,6 +148,7 @@ func (s *starterImpl) StartWebhook(ctx context.Context, stopChan chan struct{})
134148 logger .Infof ("Listening metrics on :8080" )
135149 err = http .ListenAndServe (":8080" , promhttp .HandlerFor (reg , promhttp.HandlerOpts {}))
136150 if err != nil {
151+ s .sentry .CaptureError (err )
137152 errCh <- errors .Newf ("error serving webhook metrics: %w" , err )
138153 close (stopChan )
139154 }
@@ -144,16 +159,34 @@ func (s *starterImpl) StartWebhook(ctx context.Context, stopChan chan struct{})
144159 select {
145160 case err := <- errCh :
146161 if err != nil {
162+ s .sentry .CaptureError (err )
147163 s .log .Errorf ("Server error: %v" , err )
148164 close (stopChan )
149165 s .errChan <- err
150166 }
151167 case <- ctx .Done ():
152- s .log .Info ("Shutting down servers due to context cancellation" )
168+ shutdownMess := "Shutting down servers due to context cancellation"
169+ s .sentry .CaptureMessage (shutdownMess )
170+ s .log .Info (shutdownMess )
153171 httpServer .Shutdown (ctx )
154172 close (stopChan )
155173 // Shutdown metrics server as well
156174 }
157175 }()
158176 return nil
159177}
178+
179+ // Add this recovery middleware function
180+ func SentryRecoveryMiddleware (sentrySvc sentry.SentryService ) func (http.Handler ) http.Handler {
181+ return func (next http.Handler ) http.Handler {
182+ return http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
183+ defer func () {
184+ if err := recover (); err != nil {
185+ sentrySvc .CaptureError (fmt .Errorf ("panic in webhook handler: %v" , err ))
186+ w .WriteHeader (http .StatusInternalServerError )
187+ }
188+ }()
189+ next .ServeHTTP (w , r )
190+ })
191+ }
192+ }
0 commit comments