@@ -130,109 +130,122 @@ func init() {
130130 // +kubebuilder:scaffold:scheme
131131}
132132
133- // nolint:gocyclo
134- func main () {
135- var metricsAddr string
136- var metricsCertPath , metricsCertName , metricsCertKey string
137- var webhookCertPath , webhookCertName , webhookCertKey string
138- var enableLeaderElection bool
139- var probeAddr string
140- var secureMetrics bool
141- var enableHTTP2 bool
142- var allowWeakTLSKeyLengths bool
143- var tlsOpts []func (* tls.Config )
144-
145- // Log file options
146- var enableFileLog bool
147- var logFilePath string
148- var logMaxSize int
149- var logMaxBackups int
150- var logMaxAge int
151- var logCompress bool
152-
153- // Kubernetes client rate limiter options
154- var kubeClientQPS float64
155- var kubeClientBurst int
156-
157- // Controller concurrency options
158- var concurrencyConfig ConcurrencyConfig
133+ type controllerOptions struct {
134+ metricsAddr string
135+ metricsCertPath string
136+ metricsCertName string
137+ metricsCertKey string
138+ webhookCertPath string
139+ webhookCertName string
140+ webhookCertKey string
141+ enableLeaderElection bool
142+ probeAddr string
143+ secureMetrics bool
144+ enableHTTP2 bool
145+ allowWeakTLSKeyLengths bool
146+ enableFileLog bool
147+ logFilePath string
148+ logMaxSize int
149+ logMaxBackups int
150+ logMaxAge int
151+ logCompress bool
152+ kubeClientQPS float64
153+ kubeClientBurst int
154+ concurrencyConfig ConcurrencyConfig
155+ imageCommitterImage string
156+ commitJobTimeout time.Duration
157+ snapshotRegistry string
158+ snapshotRegistryInsecure bool
159+ snapshotPushSecret string
160+ resumePullSecret string
161+ zapOptions zap.Options
162+ legacyKlogVerbosity string
163+ }
159164
160- flag .StringVar (& metricsAddr , "metrics-bind-address" , "0" , "The address the metrics endpoint binds to. " +
165+ func (o * controllerOptions ) bindFlags (fs * flag.FlagSet ) {
166+ fs .StringVar (& o .metricsAddr , "metrics-bind-address" , "0" , "The address the metrics endpoint binds to. " +
161167 "Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service." )
162- flag .StringVar (& probeAddr , "health-probe-bind-address" , ":8081" , "The address the probe endpoint binds to." )
163- flag .BoolVar (& enableLeaderElection , "leader-elect" , false ,
168+ fs .StringVar (& o . probeAddr , "health-probe-bind-address" , ":8081" , "The address the probe endpoint binds to." )
169+ fs .BoolVar (& o . enableLeaderElection , "leader-elect" , false ,
164170 "Enable leader election for controller manager. " +
165171 "Enabling this will ensure there is only one active controller manager." )
166- flag .BoolVar (& secureMetrics , "metrics-secure" , true ,
172+ fs .BoolVar (& o . secureMetrics , "metrics-secure" , true ,
167173 "If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead." )
168- flag .StringVar (& webhookCertPath , "webhook-cert-path" , "" , "The directory that contains the webhook certificate." )
169- flag .StringVar (& webhookCertName , "webhook-cert-name" , "tls.crt" , "The name of the webhook certificate file." )
170- flag .StringVar (& webhookCertKey , "webhook-cert-key" , "tls.key" , "The name of the webhook key file." )
171- flag .StringVar (& metricsCertPath , "metrics-cert-path" , "" ,
174+ fs .StringVar (& o . webhookCertPath , "webhook-cert-path" , "" , "The directory that contains the webhook certificate." )
175+ fs .StringVar (& o . webhookCertName , "webhook-cert-name" , "tls.crt" , "The name of the webhook certificate file." )
176+ fs .StringVar (& o . webhookCertKey , "webhook-cert-key" , "tls.key" , "The name of the webhook key file." )
177+ fs .StringVar (& o . metricsCertPath , "metrics-cert-path" , "" ,
172178 "The directory that contains the metrics server certificate." )
173- flag .StringVar (& metricsCertName , "metrics-cert-name" , "tls.crt" , "The name of the metrics server certificate file." )
174- flag .StringVar (& metricsCertKey , "metrics-cert-key" , "tls.key" , "The name of the metrics server key file." )
175- flag .BoolVar (& enableHTTP2 , "enable-http2" , false ,
179+ fs .StringVar (& o . metricsCertName , "metrics-cert-name" , "tls.crt" , "The name of the metrics server certificate file." )
180+ fs .StringVar (& o . metricsCertKey , "metrics-cert-key" , "tls.key" , "The name of the metrics server key file." )
181+ fs .BoolVar (& o . enableHTTP2 , "enable-http2" , false ,
176182 "If set, HTTP/2 will be enabled for the metrics and webhook servers" )
177- flag .BoolVar (
178- & allowWeakTLSKeyLengths ,
183+ fs .BoolVar (
184+ & o . allowWeakTLSKeyLengths ,
179185 "allow-weak-tls-keylengths" ,
180186 false ,
181187 "If set, allows TLS certificates below NIST 2030 minimum key/hash lengths (not recommended)." ,
182188 )
183189
184190 // Log file flags
185- flag .BoolVar (& enableFileLog , "enable-file-log" , false , "Enable log output to file" )
186- flag .StringVar (& logFilePath , "log-file-path" , "/var/log/sandbox-controller/controller.log" , "Path to the log file" )
187- flag .IntVar (& logMaxSize , "log-max-size" , 100 , "Maximum size in megabytes of the log file before it gets rotated" )
188- flag .IntVar (& logMaxBackups , "log-max-backups" , 10 , "Maximum number of old log files to retain" )
189- flag .IntVar (& logMaxAge , "log-max-age" , 30 , "Maximum number of days to retain old log files" )
190- flag .BoolVar (& logCompress , "log-compress" , true , "Compress determines if the rotated log files should be compressed using gzip" )
191- flag .Float64Var (& kubeClientQPS , "kube-client-qps" , 100 , "QPS for Kubernetes client rate limiter." )
192- flag .IntVar (& kubeClientBurst , "kube-client-burst" , 200 , "Burst for Kubernetes client rate limiter." )
193- flag .Var (& concurrencyConfig , "concurrency" , "Controller concurrency settings in format: controller1=N;controller2=M. " +
191+ fs .BoolVar (& o . enableFileLog , "enable-file-log" , false , "Enable log output to file" )
192+ fs .StringVar (& o . logFilePath , "log-file-path" , "/var/log/sandbox-controller/controller.log" , "Path to the log file" )
193+ fs .IntVar (& o . logMaxSize , "log-max-size" , 100 , "Maximum size in megabytes of the log file before it gets rotated" )
194+ fs .IntVar (& o . logMaxBackups , "log-max-backups" , 10 , "Maximum number of old log files to retain" )
195+ fs .IntVar (& o . logMaxAge , "log-max-age" , 30 , "Maximum number of days to retain old log files" )
196+ fs .BoolVar (& o . logCompress , "log-compress" , true , "Compress determines if the rotated log files should be compressed using gzip" )
197+ fs .Float64Var (& o . kubeClientQPS , "kube-client-qps" , 100 , "QPS for Kubernetes client rate limiter." )
198+ fs .IntVar (& o . kubeClientBurst , "kube-client-burst" , 200 , "Burst for Kubernetes client rate limiter." )
199+ fs .Var (& o . concurrencyConfig , "concurrency" , "Controller concurrency settings in format: controller1=N;controller2=M. " +
194200 "Available controllers: batchsandbox, pool. " +
195201 "Example: --concurrency='batchsandbox=32;pool=128'" )
196202
197203 // Image committer
198- var imageCommitterImage string
199- flag .StringVar (& imageCommitterImage , "image-committer-image" , "image-committer:dev" , "The image used for commit operations (contains nerdctl tool)." )
204+ fs .StringVar (& o .imageCommitterImage , "image-committer-image" , "image-committer:dev" , "The image used for commit operations (contains nerdctl tool)." )
200205
201206 // Commit job timeout
202- var commitJobTimeout time.Duration
203- flag .DurationVar (& commitJobTimeout , "commit-job-timeout" , 10 * time .Minute , "The timeout duration for commit jobs." )
207+ fs .DurationVar (& o .commitJobTimeout , "commit-job-timeout" , 10 * time .Minute , "The timeout duration for commit jobs." )
204208
205- var snapshotRegistry string
206- flag .StringVar (& snapshotRegistry , "snapshot-registry" , "" , "OCI registry for snapshot images (e.g., registry.example.com/snapshots)." )
209+ fs .StringVar (& o .snapshotRegistry , "snapshot-registry" , "" , "OCI registry for snapshot images (e.g., registry.example.com/snapshots)." )
207210
208- var snapshotRegistryInsecure bool
209- flag .BoolVar (& snapshotRegistryInsecure , "snapshot-registry-insecure" , false , "Use insecure registry mode when pushing snapshot images." )
211+ fs .BoolVar (& o .snapshotRegistryInsecure , "snapshot-registry-insecure" , false , "Use insecure registry mode when pushing snapshot images." )
210212
211- var snapshotPushSecret string
212- flag .StringVar (& snapshotPushSecret , "snapshot-push-secret" , "" , "K8s Secret name for pushing snapshots to registry." )
213+ fs .StringVar (& o .snapshotPushSecret , "snapshot-push-secret" , "" , "K8s Secret name for pushing snapshots to registry." )
213214
214- var resumePullSecret string
215- flag .StringVar (& resumePullSecret , "resume-pull-secret" , "" , "K8s Secret name for pulling snapshot images during resume." )
215+ fs .StringVar (& o .resumePullSecret , "resume-pull-secret" , "" , "K8s Secret name for pulling snapshot images during resume." )
216216
217- opts := zap.Options {}
218- opts .BindFlags (flag .CommandLine )
217+ o .zapOptions .BindFlags (fs )
218+ if fs .Lookup ("v" ) == nil {
219+ fs .StringVar (& o .legacyKlogVerbosity , "v" , "" , "Deprecated compatibility flag for older controller manifests; use --zap-log-level instead." )
220+ }
221+ }
222+
223+ // nolint:gocyclo
224+ func main () {
225+ var tlsOpts []func (* tls.Config )
226+
227+ options := & controllerOptions {}
228+ options .bindFlags (flag .CommandLine )
219229
220230 flag .Parse ()
221231
222232 // Setup logger with file rotation support
223233 logOpts := logging.Options {
224- Development : opts .Development ,
225- EnableFileOutput : enableFileLog ,
226- LogFilePath : logFilePath ,
227- MaxSize : logMaxSize ,
228- MaxBackups : logMaxBackups ,
229- MaxAge : logMaxAge ,
230- Compress : logCompress ,
231- ZapOptions : opts ,
234+ Development : options . zapOptions .Development ,
235+ EnableFileOutput : options . enableFileLog ,
236+ LogFilePath : options . logFilePath ,
237+ MaxSize : options . logMaxSize ,
238+ MaxBackups : options . logMaxBackups ,
239+ MaxAge : options . logMaxAge ,
240+ Compress : options . logCompress ,
241+ ZapOptions : options . zapOptions ,
232242 }
233243
234244 logger := logging .NewLoggerWithZapOptions (logOpts )
235245 ctrl .SetLogger (logger )
246+ if options .legacyKlogVerbosity != "" {
247+ setupLog .Info ("deprecated --v flag ignored; use --zap-log-level instead" , "v" , options .legacyKlogVerbosity )
248+ }
236249
237250 // if the enable-http2 flag is false (the default), http/2 should be disabled
238251 // due to its vulnerabilities. More specifically, disabling http/2 will
@@ -249,7 +262,7 @@ func main() {
249262 c .MinVersion = tls .VersionTLS12
250263 })
251264
252- if ! enableHTTP2 {
265+ if ! options . enableHTTP2 {
253266 tlsOpts = append (tlsOpts , disableHTTP2 )
254267 }
255268
@@ -259,10 +272,10 @@ func main() {
259272 // Initial webhook TLS options
260273 webhookTLSOpts := tlsOpts
261274
262- if len (webhookCertPath ) > 0 {
263- webhookCertFile := filepath .Join (webhookCertPath , webhookCertName )
264- webhookKeyFile := filepath .Join (webhookCertPath , webhookCertKey )
265- if ! allowWeakTLSKeyLengths {
275+ if len (options . webhookCertPath ) > 0 {
276+ webhookCertFile := filepath .Join (options . webhookCertPath , options . webhookCertName )
277+ webhookKeyFile := filepath .Join (options . webhookCertPath , options . webhookCertKey )
278+ if ! options . allowWeakTLSKeyLengths {
266279 if err := cryptoutil .ValidateCertificateKeyPair (webhookCertFile , webhookKeyFile ); err != nil {
267280 setupLog .Error (err , "Webhook certificate does not meet NIST minimum key/hash requirements" ,
268281 "webhook-cert-file" , webhookCertFile , "webhook-key-file" , webhookKeyFile )
@@ -271,7 +284,7 @@ func main() {
271284 }
272285
273286 setupLog .Info ("Initializing webhook certificate watcher using provided certificates" ,
274- "webhook-cert-path" , webhookCertPath , "webhook-cert-name" , webhookCertName , "webhook-cert-key" , webhookCertKey )
287+ "webhook-cert-path" , options . webhookCertPath , "webhook-cert-name" , options . webhookCertName , "webhook-cert-key" , options . webhookCertKey )
275288
276289 var err error
277290 webhookCertWatcher , err = certwatcher .New (
@@ -289,7 +302,7 @@ func main() {
289302 if err != nil {
290303 return nil , err
291304 }
292- if allowWeakTLSKeyLengths {
305+ if options . allowWeakTLSKeyLengths {
293306 return cert , nil
294307 }
295308 if err := cryptoutil .ValidateTLSCertificate (webhookCertFile , cert ); err != nil {
@@ -309,12 +322,12 @@ func main() {
309322 // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/metrics/server
310323 // - https://book.kubebuilder.io/reference/metrics.html
311324 metricsServerOptions := metricsserver.Options {
312- BindAddress : metricsAddr ,
313- SecureServing : secureMetrics ,
325+ BindAddress : options . metricsAddr ,
326+ SecureServing : options . secureMetrics ,
314327 TLSOpts : tlsOpts ,
315328 }
316329
317- if secureMetrics {
330+ if options . secureMetrics {
318331 // FilterProvider is used to protect the metrics endpoint with authn/authz.
319332 // These configurations ensure that only authorized users and service accounts
320333 // can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info:
@@ -330,10 +343,10 @@ func main() {
330343 // - [METRICS-WITH-CERTS] at config/default/kustomization.yaml to generate and use certificates
331344 // managed by cert-manager for the metrics server.
332345 // - [PROMETHEUS-WITH-CERTS] at config/prometheus/kustomization.yaml for TLS certification.
333- if len (metricsCertPath ) > 0 {
334- metricsCertFile := filepath .Join (metricsCertPath , metricsCertName )
335- metricsKeyFile := filepath .Join (metricsCertPath , metricsCertKey )
336- if ! allowWeakTLSKeyLengths && metricsAddr != "0" && secureMetrics {
346+ if len (options . metricsCertPath ) > 0 {
347+ metricsCertFile := filepath .Join (options . metricsCertPath , options . metricsCertName )
348+ metricsKeyFile := filepath .Join (options . metricsCertPath , options . metricsCertKey )
349+ if ! options . allowWeakTLSKeyLengths && options . metricsAddr != "0" && options . secureMetrics {
337350 if err := cryptoutil .ValidateCertificateKeyPair (metricsCertFile , metricsKeyFile ); err != nil {
338351 setupLog .Error (err , "Metrics certificate does not meet NIST minimum key/hash requirements" ,
339352 "metrics-cert-file" , metricsCertFile , "metrics-key-file" , metricsKeyFile )
@@ -342,7 +355,7 @@ func main() {
342355 }
343356
344357 setupLog .Info ("Initializing metrics certificate watcher using provided certificates" ,
345- "metrics-cert-path" , metricsCertPath , "metrics-cert-name" , metricsCertName , "metrics-cert-key" , metricsCertKey )
358+ "metrics-cert-path" , options . metricsCertPath , "metrics-cert-name" , options . metricsCertName , "metrics-cert-key" , options . metricsCertKey )
346359
347360 var err error
348361 metricsCertWatcher , err = certwatcher .New (
@@ -360,7 +373,7 @@ func main() {
360373 if err != nil {
361374 return nil , err
362375 }
363- if allowWeakTLSKeyLengths {
376+ if options . allowWeakTLSKeyLengths {
364377 return cert , nil
365378 }
366379 if err := cryptoutil .ValidateTLSCertificate (metricsCertFile , cert ); err != nil {
@@ -373,19 +386,19 @@ func main() {
373386
374387 config := ctrl .GetConfigOrDie ()
375388 // Set client rate limiter if specified
376- if kubeClientQPS > 0 {
377- config .QPS = float32 (kubeClientQPS )
389+ if options . kubeClientQPS > 0 {
390+ config .QPS = float32 (options . kubeClientQPS )
378391 }
379- if kubeClientBurst > 0 {
380- config .Burst = kubeClientBurst
392+ if options . kubeClientBurst > 0 {
393+ config .Burst = options . kubeClientBurst
381394 }
382395
383396 mgr , err := ctrl .NewManager (config , ctrl.Options {
384397 Scheme : scheme ,
385398 Metrics : metricsServerOptions ,
386399 WebhookServer : webhookServer ,
387- HealthProbeBindAddress : probeAddr ,
388- LeaderElection : enableLeaderElection ,
400+ HealthProbeBindAddress : options . probeAddr ,
401+ LeaderElection : options . enableLeaderElection ,
389402 LeaderElectionID : "2fa1c467.opensandbox.io" ,
390403 // LeaderElectionReleaseOnCancel causes the leader to voluntarily release the lease
391404 // when the Manager is stopped, allowing a new leader to acquire it without waiting
@@ -407,8 +420,8 @@ func main() {
407420 batchSandboxKindName = strings .ToLower (getKindFromType (& sandboxv1alpha1.BatchSandbox {}))
408421 poolKindName = strings .ToLower (getKindFromType (& sandboxv1alpha1.Pool {}))
409422 )
410- batchSandboxConcurrency := concurrencyConfig .Get (batchSandboxKindName , defaultBatchSandboxConcurrency )
411- poolConcurrency := concurrencyConfig .Get (poolKindName , defaultPoolConcurrency )
423+ batchSandboxConcurrency := options . concurrencyConfig .Get (batchSandboxKindName , defaultBatchSandboxConcurrency )
424+ poolConcurrency := options . concurrencyConfig .Get (poolKindName , defaultPoolConcurrency )
412425 setupLog .Info ("controller concurrency configured" , batchSandboxKindName , batchSandboxConcurrency , poolKindName , poolConcurrency )
413426
414427 profileStore := poolassign .NewProfileStore ()
@@ -422,7 +435,7 @@ func main() {
422435 Client : mgr .GetClient (),
423436 Scheme : mgr .GetScheme (),
424437 Recorder : mgr .GetEventRecorderFor ("batchsandbox-controller" ),
425- ResumePullSecret : resumePullSecret ,
438+ ResumePullSecret : options . resumePullSecret ,
426439 ProfileStore : profileStore ,
427440 }).SetupWithManager (mgr , batchSandboxConcurrency ); err != nil {
428441 setupLog .Error (err , "unable to create controller" , "controller" , "BatchSandbox" )
@@ -442,11 +455,11 @@ func main() {
442455 Client : mgr .GetClient (),
443456 Scheme : mgr .GetScheme (),
444457 Recorder : mgr .GetEventRecorderFor ("sandboxsnapshot-controller" ),
445- ImageCommitterImage : imageCommitterImage ,
446- CommitJobTimeout : commitJobTimeout ,
447- SnapshotRegistry : snapshotRegistry ,
448- SnapshotRegistryInsecure : snapshotRegistryInsecure ,
449- SnapshotPushSecret : snapshotPushSecret ,
458+ ImageCommitterImage : options . imageCommitterImage ,
459+ CommitJobTimeout : options . commitJobTimeout ,
460+ SnapshotRegistry : options . snapshotRegistry ,
461+ SnapshotRegistryInsecure : options . snapshotRegistryInsecure ,
462+ SnapshotPushSecret : options . snapshotPushSecret ,
450463 }).SetupWithManager (mgr ); err != nil {
451464 setupLog .Error (err , "unable to create controller" , "controller" , "SandboxSnapshot" )
452465 os .Exit (1 )
0 commit comments