From 6928ad16b6ee50d1d20d310621946596202c103f Mon Sep 17 00:00:00 2001 From: Aaron Schlesinger <70865+arschles@users.noreply.github.com> Date: Wed, 10 Nov 2021 10:39:15 -0800 Subject: [PATCH] Fixing operator startup (#315) * fixing operator startup code Signed-off-by: Aaron Schlesinger * updating go vsn Signed-off-by: Aaron Schlesinger --- go.mod | 2 +- operator/main.go | 93 ++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 76 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index c992bd97..ac642073 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/kedacore/http-add-on -go 1.16 +go 1.17 require ( github.com/go-logr/logr v0.4.0 diff --git a/operator/main.go b/operator/main.go index 9f0a5d33..7eb9bca5 100644 --- a/operator/main.go +++ b/operator/main.go @@ -24,6 +24,7 @@ import ( "os" "golang.org/x/sync/errgroup" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" @@ -53,6 +54,9 @@ func init() { } func main() { + ctx := ctrl.SetupSignalHandler() + ctrl.SetLogger(zap.New(zap.UseDevMode(true))) + var metricsAddr string var enableLeaderElection bool var adminPort int @@ -85,10 +89,22 @@ func main() { ) os.Exit(1) } - - ctrl.SetLogger(zap.New(zap.UseDevMode(true))) - - ctx := context.Background() + if err := ensureConfigMap( + ctx, + setupLog, + baseConfig.Namespace, + routing.ConfigMapRoutingTableName, + ); err != nil { + setupLog.Error( + err, + "unable to find routing table ConfigMap", + "namespace", + baseConfig.Namespace, + "name", + routing.ConfigMapRoutingTableName, + ) + os.Exit(1) + } mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ Scheme: scheme, @@ -103,18 +119,6 @@ func main() { } cl := mgr.GetClient() - namespace := baseConfig.Namespace - // crash if the routing table ConfigMap couldn't be found - if _, err := k8s.GetConfigMap(ctx, cl, namespace, routing.ConfigMapRoutingTableName); err != nil { - setupLog.Error( - err, - "Couldn't fetch routing table config map", - "configMapName", - routing.ConfigMapRoutingTableName, - ) - os.Exit(1) - } - routingTable := routing.NewTable() if err := (&controllers.HTTPScaledObjectReconciler{ Client: cl, @@ -130,17 +134,22 @@ func main() { } // +kubebuilder:scaffold:builder - errGrp, _ := errgroup.WithContext(ctx) + errGrp, ctx := errgroup.WithContext( + ctx, + ) + ctx, done := context.WithCancel(ctx) // start the control loop errGrp.Go(func() error { + defer done() setupLog.Info("starting manager") - return mgr.Start(ctrl.SetupSignalHandler()) + return mgr.Start(ctx) }) // start the admin server to serve routing table information // to the interceptors errGrp.Go(func() error { + defer done() return runAdminServer( ctx, ctrl.Log, @@ -182,3 +191,51 @@ func runAdminServer( ) return kedahttp.ServeContext(ctx, addr, mux) } + +// ensureConfigMap returns a non-nil error if the config +// map in the given namespace with the given name +// does not exist, or there was an error finding it. +// +// it returns a nil error if it could be fetched. +// this function works with its own Kubernetes client and +// is intended for use on operator startup, and should +// not be used with the controller library's client, +// since that is not usable until after the controller +// has started up. +func ensureConfigMap( + ctx context.Context, + lggr logr.Logger, + ns, + name string, +) error { + // we need to get our own Kubernetes clientset + // here, rather than using the client.Client from + // the manager because the client will not + // be instantiated by the time we call this. + // You need to start the manager before that client + // is usable. + clset, _, err := k8s.NewClientset() + if err != nil { + lggr.Error( + err, + "couldn't get new clientset", + ) + return err + } + if _, err := clset.CoreV1().ConfigMaps(ns).Get( + ctx, + name, + metav1.GetOptions{}, + ); err != nil { + lggr.Error( + err, + "couldn't find config map", + "namespace", + ns, + "name", + name, + ) + return err + } + return nil +}