Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

main.go fixes and improvements #24

Merged
merged 9 commits into from
Jan 6, 2021
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
k8s.io/api v0.17.16
k8s.io/apimachinery v0.17.16
k8s.io/client-go v0.17.16
k8s.io/klog v1.0.0
k8s.io/utils v0.0.0-20201110183641-67b214c5f920 // indirect
sigs.k8s.io/cluster-api v0.3.12
sigs.k8s.io/controller-runtime v0.5.14
Expand Down
147 changes: 69 additions & 78 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,18 @@ import (
"os"
"time"

"github.com/tinkerbell/cluster-api-provider-tinkerbell/controllers"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"k8s.io/client-go/tools/record"
"k8s.io/klog"
"k8s.io/klog/klogr"
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"

infrastructurev1alpha3 "github.com/tinkerbell/cluster-api-provider-tinkerbell/api/v1alpha3"
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3"
"github.com/tinkerbell/cluster-api-provider-tinkerbell/controllers"
// +kubebuilder:scaffold:imports
)

Expand All @@ -49,115 +50,105 @@ func init() {
// +kubebuilder:scaffold:scheme
}

//nolint:funlen,gomnd
func main() {
var (
enableLeaderElection bool
leaderElectionNamespace string
healthAddr string
metricsAddr string
webhookPort int
syncPeriod time.Duration
watchNamespace string
)
// optionsFromFlags parse CLI flags and converts them to controller runtime options.
func optionsFromFlags() ctrl.Options {
klog.InitFlags(nil)

// Machine and cluster operations can create enough events to trigger the event recorder spam filter
// Setting the burst size higher ensures all events will be recorded and submitted to the API
broadcaster := record.NewBroadcasterWithCorrelatorOptions(record.CorrelatorOptions{
BurstSize: 100, //nolint:gomnd
})

var syncPeriod time.Duration

options := ctrl.Options{
Scheme: scheme,
LeaderElectionID: "controller-leader-election-capt",
EventBroadcaster: broadcaster,
SyncPeriod: &syncPeriod,
}

flag.BoolVar(&enableLeaderElection, "enable-leader-election", false,
flag.BoolVar(&options.LeaderElection, "enable-leader-election", false,
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")

flag.StringVar(
&leaderElectionNamespace,
"leader-election-namespace",
"",
flag.StringVar(&options.LeaderElectionNamespace, "leader-election-namespace", "",
"Namespace that the controller performs leader election in. "+
"If unspecified, the controller will discover which namespace it is running in.",
)

flag.StringVar(&healthAddr,
"health-addr",
":9440",
"The address the health endpoint binds to.",
)
flag.StringVar(&options.HealthProbeBindAddress, "health-addr", ":9440", "The address the health endpoint binds to.")

flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
flag.StringVar(&options.MetricsBindAddress, "metrics-addr", ":8080", "The address the metric endpoint binds to.")

flag.DurationVar(&syncPeriod,
"sync-period",
10*time.Minute,
flag.DurationVar(&syncPeriod, "sync-period", 10*time.Minute, //nolint:gomnd
"The minimum interval at which watched resources are reconciled (e.g. 15m)",
)

flag.StringVar(
&watchNamespace,
"namespace",
"",
flag.StringVar(&options.Namespace, "namespace", "",
"Namespace that the controller watches to reconcile cluster-api objects. "+
"If unspecified, the controller watches for cluster-api objects across all namespaces.",
)

flag.IntVar(&webhookPort,
"webhook-port",
0,
flag.IntVar(&options.Port, "webhook-port", 0,
"Webhook Server port, disabled by default. When enabled, the manager will only "+
"work as webhook server, no reconcilers are installed.",
)

flag.Parse()

ctrl.SetLogger(zap.New(zap.UseDevMode(true)))
return options
}

if watchNamespace != "" {
setupLog.Info("Watching cluster-api objects only in namespace for reconciliation", "namespace", watchNamespace)
func validateOptions(options ctrl.Options) error {
if options.Namespace != "" {
setupLog.Info("Watching cluster-api objects only in namespace for reconciliation", "namespace", options.Namespace)
}

// Machine and cluster operations can create enough events to trigger the event recorder spam filter
// Setting the burst size higher ensures all events will be recorded and submitted to the API
broadcaster := record.NewBroadcasterWithCorrelatorOptions(record.CorrelatorOptions{
BurstSize: 100,
})
if options.Port != 0 {
// TODO: add the webhook configuration
return errors.New("webhook not implemented")
}

mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
MetricsBindAddress: metricsAddr,
Port: webhookPort,
EventBroadcaster: broadcaster,
LeaderElection: enableLeaderElection,
LeaderElectionID: "controller-leader-election-capt",
LeaderElectionNamespace: leaderElectionNamespace,
Namespace: watchNamespace,
SyncPeriod: &syncPeriod,
HealthProbeBindAddress: healthAddr,
})
return nil
}

func main() {
ctrl.SetLogger(klogr.New())

options := optionsFromFlags()

if err := validateOptions(options); err != nil {
setupLog.Error(err, "validating controllers configuration")
os.Exit(1)
}

mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), options)
if err != nil {
setupLog.Error(err, "unable to start manager")
os.Exit(1)
}

// TODO: Get a Tinkerbell client.

if webhookPort == 0 {
if err = (&controllers.TinkerbellClusterReconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("TinerellCluster"),
Recorder: mgr.GetEventRecorderFor("tinerellcluster-controller"),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "TinkerbellCluster")
os.Exit(1)
}

if err = (&controllers.TinkerbellMachineReconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("TinkerbellMachine"),
Scheme: mgr.GetScheme(),
Recorder: mgr.GetEventRecorderFor("tinkerbellmachine-controller"),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "TinkerbellMachine")
os.Exit(1)
}
} else {
// TODO: add the webhook configuration
setupLog.Error(errors.New("webhook not implemented"), "webhook", "not available")
if err = (&controllers.TinkerbellClusterReconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("TinerellCluster"),
Recorder: mgr.GetEventRecorderFor("tinerellcluster-controller"),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "TinkerbellCluster")
os.Exit(1)
}

if err = (&controllers.TinkerbellMachineReconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("TinkerbellMachine"),
Scheme: mgr.GetScheme(),
Recorder: mgr.GetEventRecorderFor("tinkerbellmachine-controller"),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "TinkerbellMachine")
os.Exit(1)
}
// +kubebuilder:scaffold:builder
Expand Down