package controller import ( "fmt" "net/http" "time" "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/webhook" ) var ( defaultMetricsBindAddress = ":8080" defaultLeaderElection = false ) // private options struct, this struct is mutated via the public `Option` // functions type options struct { config *rest.Config ctrlOptions ctrl.Options webHookOptions webhook.Options } // Option is used to configure a controller type Option func(*options) // WithCfg sets an explicit K8s client rest configuration, if one isn't provided, // the `ctrl.GetConfigOrDie()` is used. func WithCfg(c *rest.Config) Option { return func(o *options) { o.config = c } } // WithLeaderElection enables leader election for the controller, defaults to // false func WithLeaderElection() Option { return func(o *options) { o.ctrlOptions.LeaderElection = true } } // WithMetricsAddress sets the specific bind address for the controller, defaults // to ":8080" func WithMetricsAddress(a string) Option { return func(o *options) { o.ctrlOptions.Metrics.BindAddress = a } } // WithCertDir is the directory that contains the server key and certificate. func WithCertDir(certDir string) Option { return func(o *options) { o.webHookOptions.CertDir = certDir } } // WithPort is the port that the webhook server serves at. func WithPort(port int) Option { return func(o *options) { o.webHookOptions.Port = port } } func WithPProf(route string, h http.Handler) Option { return func(o *options) { o.ctrlOptions.Metrics.ExtraHandlers[route] = h } } func WithGracefulTimeout(timeout time.Duration) Option { return func(o *options) { o.ctrlOptions.GracefulShutdownTimeout = &timeout } } // ProcessOptions applies the provided options to the default controller // configuration and produces a K8s client configuration and base set of options // for creating a controller with the controller-runtime package. func ProcessOptions(opts ...Option) (*rest.Config, ctrl.Options) { o := &options{ ctrlOptions: ctrl.Options{ Metrics: metricsserver.Options{BindAddress: defaultMetricsBindAddress}, LeaderElection: defaultLeaderElection}, } for _, opt := range opts { opt(o) } if o.config == nil { // we don't use ctrl.GetConfigOrDie() here so that we can loudly panic, // since consumers won't be able to do anythin with the error. // if you call ctrl.GetConfigOrDie() and the logger has not been set up, // you won't get any logs. var err error o.config, err = ctrl.GetConfig() if err != nil { panic(fmt.Sprintf("failed to get Kube client config: %s", err.Error())) } } o.ctrlOptions.WebhookServer = webhook.NewServer(o.webHookOptions) return o.config, o.ctrlOptions }