@@ -45,6 +45,7 @@ import (
45
45
"sigs.k8s.io/controller-runtime/pkg/healthz"
46
46
"sigs.k8s.io/controller-runtime/pkg/log/zap"
47
47
"sigs.k8s.io/controller-runtime/pkg/manager"
48
+ "sigs.k8s.io/controller-runtime/pkg/metrics/server"
48
49
49
50
infrav1 "github.com/nutanix-cloud-native/cluster-api-provider-nutanix/api/v1beta1"
50
51
"github.com/nutanix-cloud-native/cluster-api-provider-nutanix/controllers"
@@ -69,12 +70,26 @@ const (
69
70
defaultMaxConcurrentReconciles = 10
70
71
)
71
72
73
+ type options struct {
74
+ enableLeaderElection bool
75
+ healthProbeAddr string
76
+ maxConcurrentReconciles int
77
+
78
+ rateLimiterBaseDelay time.Duration
79
+ rateLimiterMaxDelay time.Duration
80
+ rateLimiterBucketSize int
81
+ rateLimiterQPS int
82
+
83
+ managerOptions capiflags.ManagerOptions
84
+ zapOptions zap.Options
85
+ }
86
+
72
87
type managerConfig struct {
73
88
enableLeaderElection bool
74
- probeAddr string
89
+ healthProbeAddr string
75
90
concurrentReconcilesNutanixCluster int
76
91
concurrentReconcilesNutanixMachine int
77
- managerOptions capiflags. ManagerOptions
92
+ metricsServerOpts server. Options
78
93
79
94
logger logr.Logger
80
95
restConfig * rest.Config
@@ -126,42 +141,82 @@ func validateRateLimiterConfig(baseDelay, maxDelay time.Duration, bucketSize, qp
126
141
return nil
127
142
}
128
143
129
- func parseFlags (config * managerConfig ) {
130
- capiflags .AddManagerOptions (pflag .CommandLine , & config .managerOptions )
131
- pflag .StringVar (& config .probeAddr , "health-probe-bind-address" , ":8081" , "The address the probe endpoint binds to." )
132
- pflag .BoolVar (& config .enableLeaderElection , "leader-elect" , false ,
144
+ func initializeFlags () * options {
145
+ opts := & options {}
146
+
147
+ // Add the controller-runtime flags to the standard library FlagSet.
148
+ ctrl .RegisterFlags (flag .CommandLine )
149
+
150
+ // Add the Cluster API flags to the pflag FlagSet.
151
+ capiflags .AddManagerOptions (pflag .CommandLine , & opts .managerOptions )
152
+
153
+ // Add zap flags to the standard libary FlagSet.
154
+ opts .zapOptions .BindFlags (flag .CommandLine )
155
+
156
+ // Add our own flags to the pflag FlagSet.
157
+ pflag .StringVar (& opts .healthProbeAddr , "health-probe-bind-address" , ":8081" , "The address the probe endpoint binds to." )
158
+ pflag .BoolVar (& opts .enableLeaderElection , "leader-elect" , false ,
133
159
"Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager." )
134
- var maxConcurrentReconciles int
135
- pflag .IntVar (& maxConcurrentReconciles , "max-concurrent-reconciles" , defaultMaxConcurrentReconciles ,
160
+
161
+ pflag .IntVar (& opts . maxConcurrentReconciles , "max-concurrent-reconciles" , defaultMaxConcurrentReconciles ,
136
162
"The maximum number of allowed, concurrent reconciles." )
137
163
138
- var baseDelay , maxDelay time.Duration
139
- var bucketSize , qps int
140
- pflag .DurationVar (& baseDelay , "rate-limiter-base-delay" , 500 * time .Millisecond , "The base delay for the rate limiter." )
141
- pflag .DurationVar (& maxDelay , "rate-limiter-max-delay" , 15 * time .Minute , "The maximum delay for the rate limiter." )
142
- pflag .IntVar (& bucketSize , "rate-limiter-bucket-size" , 100 , "The bucket size for the rate limiter." )
143
- pflag .IntVar (& qps , "rate-limiter-qps" , 10 , "The QPS for the rate limiter." )
164
+ pflag .DurationVar (& opts .rateLimiterBaseDelay , "rate-limiter-base-delay" , 500 * time .Millisecond , "The base delay for the rate limiter." )
165
+ pflag .DurationVar (& opts .rateLimiterMaxDelay , "rate-limiter-max-delay" , 15 * time .Minute , "The maximum delay for the rate limiter." )
166
+ pflag .IntVar (& opts .rateLimiterBucketSize , "rate-limiter-bucket-size" , 100 , "The bucket size for the rate limiter." )
167
+ pflag .IntVar (& opts .rateLimiterQPS , "rate-limiter-qps" , 10 , "The QPS for the rate limiter." )
144
168
145
- opts := zap.Options {
146
- TimeEncoder : zapcore .RFC3339TimeEncoder ,
147
- }
148
- opts .BindFlags (flag .CommandLine )
149
-
150
- logger := zap .New (zap .UseFlagOptions (& opts ))
151
- ctrl .SetLogger (logger )
169
+ // At this point, we should be done adding flags to the standard library FlagSet, flag.CommandLine.
170
+ // So we can include the flags that third-party libraries, e.g. controller-runtime, and zap,
171
+ // have added to the standard library FlagSet, we merge it into the pflag FlagSet.
152
172
pflag .CommandLine .AddGoFlagSet (flag .CommandLine )
173
+
174
+ // Parse flags.
153
175
pflag .Parse ()
154
176
155
- config .concurrentReconcilesNutanixCluster = maxConcurrentReconciles
156
- config .concurrentReconcilesNutanixMachine = maxConcurrentReconciles
177
+ return opts
178
+ }
179
+
180
+ func initializeConfig (opts * options ) (* managerConfig , error ) {
181
+ config := & managerConfig {
182
+ enableLeaderElection : opts .enableLeaderElection ,
183
+ healthProbeAddr : opts .healthProbeAddr ,
184
+ }
157
185
158
- rateLimiter , err := compositeRateLimiter ( baseDelay , maxDelay , bucketSize , qps )
186
+ _ , metricsServerOpts , err := capiflags . GetManagerOptions ( opts . managerOptions )
159
187
if err != nil {
160
- config .logger .Error (err , "unable to create composite rate limiter" )
161
- os .Exit (1 )
188
+ return nil , fmt .Errorf ("unable to get metrics server options: %w" , err )
189
+ }
190
+ if metricsServerOpts == nil {
191
+ return nil , errors .New ("parsed manager options are nil" )
162
192
}
193
+ config .metricsServerOpts = * metricsServerOpts
194
+
195
+ config .concurrentReconcilesNutanixCluster = opts .maxConcurrentReconciles
196
+ config .concurrentReconcilesNutanixMachine = opts .maxConcurrentReconciles
163
197
198
+ rateLimiter , err := compositeRateLimiter (opts .rateLimiterBaseDelay , opts .rateLimiterMaxDelay , opts .rateLimiterBucketSize , opts .rateLimiterQPS )
199
+ if err != nil {
200
+ return nil , fmt .Errorf ("unable to create composite rate limiter: %w" , err )
201
+ }
164
202
config .rateLimiter = rateLimiter
203
+
204
+ zapOptions := opts .zapOptions
205
+ zapOptions .TimeEncoder = zapcore .RFC3339TimeEncoder
206
+ config .logger = zap .New (zap .UseFlagOptions (& zapOptions ))
207
+
208
+ // Configure controller-runtime logger before using calling any controller-runtime functions.
209
+ // Otherwise, the user will not see warnings and errors logged by these functions.
210
+ ctrl .SetLogger (config .logger )
211
+
212
+ // Before calling GetConfigOrDie, we have parsed flags, because the function reads value of
213
+ // the--kubeconfig flag.
214
+ config .restConfig , err = ctrl .GetConfig ()
215
+ if err != nil {
216
+ return nil , fmt .Errorf ("failed to load kubeconfig: %w" , err )
217
+ }
218
+
219
+ return config , nil
165
220
}
166
221
167
222
func setupLogger () logr.Logger {
@@ -276,19 +331,10 @@ func runManager(ctx context.Context, mgr manager.Manager, config *managerConfig)
276
331
}
277
332
278
333
func initializeManager (config * managerConfig ) (manager.Manager , error ) {
279
- _ , metricsOpts , err := capiflags .GetManagerOptions (config .managerOptions )
280
- if err != nil {
281
- return nil , fmt .Errorf ("unable to get manager options: %w" , err )
282
- }
283
-
284
- if metricsOpts == nil {
285
- return nil , errors .New ("parsed manager options are nil" )
286
- }
287
-
288
334
mgr , err := ctrl .NewManager (config .restConfig , ctrl.Options {
289
335
Scheme : scheme ,
290
- Metrics : * metricsOpts ,
291
- HealthProbeBindAddress : config .probeAddr ,
336
+ Metrics : config . metricsServerOpts ,
337
+ HealthProbeBindAddress : config .healthProbeAddr ,
292
338
LeaderElection : config .enableLeaderElection ,
293
339
LeaderElectionID : "f265110d.cluster.x-k8s.io" ,
294
340
})
@@ -306,16 +352,17 @@ func initializeManager(config *managerConfig) (manager.Manager, error) {
306
352
func main () {
307
353
logger := setupLogger ()
308
354
309
- config := & managerConfig {}
310
- parseFlags (config )
355
+ logger .Info ("Initializing Nutanix Cluster API Infrastructure Provider" , "Git Hash" , gitCommitHash )
311
356
312
- // Flags must be parsed before calling GetConfigOrDie, because
313
- // it reads the value of the--kubeconfig flag.
314
- config .restConfig = ctrl .GetConfigOrDie ()
357
+ opts := initializeFlags ()
358
+ // After this point, we must not add flags to either the pflag, or the standard library FlagSets.
315
359
316
- config .logger = logger
360
+ config , err := initializeConfig (opts )
361
+ if err != nil {
362
+ logger .Error (err , "unable to configure manager" )
363
+ os .Exit (1 )
364
+ }
317
365
318
- logger .Info ("Initializing Nutanix Cluster API Infrastructure Provider" , "Git Hash" , gitCommitHash )
319
366
mgr , err := initializeManager (config )
320
367
if err != nil {
321
368
logger .Error (err , "unable to create manager" )
0 commit comments