diff --git a/cmd/controller/app/controller.go b/cmd/controller/app/controller.go index f9ee217af..e8f2d37c2 100644 --- a/cmd/controller/app/controller.go +++ b/cmd/controller/app/controller.go @@ -56,7 +56,7 @@ func Run(opts *options.ControllerOptions, stopCh <-chan struct{}) { rootCtx = logf.NewContext(rootCtx, nil, "controller") log := logf.FromContext(rootCtx) - ctx, kubeCfg, err := buildControllerContext(rootCtx, opts) + ctx, kubeCfg, err := buildControllerContext(rootCtx, stopCh, opts) if err != nil { log.Error(err, "error building controller context", "options", opts) @@ -88,6 +88,11 @@ func Run(opts *options.ControllerOptions, stopCh <-chan struct{}) { } wg.Add(1) + iface, err := fn(ctx) + if err != nil { + log.Error(err, "error starting controller") + os.Exit(1) + } go func(n string, fn controller.Interface) { defer wg.Done() log.Info("starting controller") @@ -99,7 +104,7 @@ func Run(opts *options.ControllerOptions, stopCh <-chan struct{}) { log.Error(err, "error starting controller") os.Exit(1) } - }(n, fn(ctx)) + }(n, iface) } log.V(4).Info("starting shared informer factories") @@ -126,9 +131,8 @@ func Run(opts *options.ControllerOptions, stopCh <-chan struct{}) { panic("unreachable") } -func buildControllerContext(ctx context.Context, opts *options.ControllerOptions) (*controller.Context, *rest.Config, error) { +func buildControllerContext(ctx context.Context, stopCh <-chan struct{}, opts *options.ControllerOptions) (*controller.Context, *rest.Config, error) { log := logf.FromContext(ctx, "build-context") - // Load the users Kubernetes config kubeCfg, err := kube.KubeConfig(opts.APIServerHost) if err != nil { @@ -187,6 +191,8 @@ func buildControllerContext(ctx context.Context, opts *options.ControllerOptions kubeSharedInformerFactory := kubeinformers.NewFilteredSharedInformerFactory(cl, time.Second*30, opts.Namespace, nil) return &controller.Context{ RootContext: ctx, + StopCh: stopCh, + RESTConfig: kubeCfg, Client: cl, CMClient: intcl, Recorder: recorder, diff --git a/pkg/controller/BUILD.bazel b/pkg/controller/BUILD.bazel index 509f4cd07..80db00715 100644 --- a/pkg/controller/BUILD.bazel +++ b/pkg/controller/BUILD.bazel @@ -18,6 +18,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/tools/cache:go_default_library", "//vendor/k8s.io/client-go/tools/record:go_default_library", "//vendor/k8s.io/client-go/util/workqueue:go_default_library", diff --git a/pkg/controller/acmechallenges/controller.go b/pkg/controller/acmechallenges/controller.go index ed1f30f75..fe5cfa752 100644 --- a/pkg/controller/acmechallenges/controller.go +++ b/pkg/controller/acmechallenges/controller.go @@ -67,7 +67,7 @@ type Controller struct { scheduler *scheduler.Scheduler } -func New(ctx *controllerpkg.Context) *Controller { +func New(ctx *controllerpkg.Context) (*Controller, error) { ctrl := &Controller{Context: *ctx} ctrl.syncHandler = ctrl.processNextWorkItem @@ -110,7 +110,7 @@ func New(ctx *controllerpkg.Context) *Controller { ctrl.scheduler = scheduler.New(ctrl.challengeLister) ctrl.ctx = logf.NewContext(ctx.RootContext, nil, ControllerName) - return ctrl + return ctrl, nil } func (c *Controller) Run(workers int, stopCh <-chan struct{}) error { @@ -249,7 +249,11 @@ const ( ) func init() { - controllerpkg.Register(ControllerName, func(ctx *controllerpkg.Context) controllerpkg.Interface { - return New(ctx).Run + controllerpkg.Register(ControllerName, func(ctx *controllerpkg.Context) (controllerpkg.Interface, error) { + i, err := New(ctx) + if err != nil { + return nil, err + } + return i.Run, nil }) } diff --git a/pkg/controller/acmechallenges/util_test.go b/pkg/controller/acmechallenges/util_test.go index 3872142af..bd263b299 100644 --- a/pkg/controller/acmechallenges/util_test.go +++ b/pkg/controller/acmechallenges/util_test.go @@ -97,7 +97,11 @@ func (f *controllerFixture) Finish(t *testing.T, args ...interface{}) { func (f *controllerFixture) buildFakeController(b *test.Builder, issuer v1alpha1.GenericIssuer) *Controller { b.Start() - c := New(b.Context) + c, err := New(b.Context) + if err != nil { + b.T.Errorf("error constructing controller: %v", err) + b.T.FailNow() + } c.acmeHelper = f c.helper = f c.httpSolver = f.HTTP01 diff --git a/pkg/controller/acmeorders/controller.go b/pkg/controller/acmeorders/controller.go index a5e9a13ea..7b41955da 100644 --- a/pkg/controller/acmeorders/controller.go +++ b/pkg/controller/acmeorders/controller.go @@ -237,7 +237,7 @@ const ( ) func init() { - controllerpkg.Register(ControllerName, func(ctx *controllerpkg.Context) controllerpkg.Interface { - return New(ctx).Run + controllerpkg.Register(ControllerName, func(ctx *controllerpkg.Context) (controllerpkg.Interface, error) { + return New(ctx).Run, nil }) } diff --git a/pkg/controller/certificates/controller.go b/pkg/controller/certificates/controller.go index 394ace22e..598115c99 100644 --- a/pkg/controller/certificates/controller.go +++ b/pkg/controller/certificates/controller.go @@ -207,7 +207,7 @@ const ( ) func init() { - controllerpkg.Register(ControllerName, func(ctx *controllerpkg.Context) controllerpkg.Interface { - return New(ctx).Run + controllerpkg.Register(ControllerName, func(ctx *controllerpkg.Context) (controllerpkg.Interface, error) { + return New(ctx).Run, nil }) } diff --git a/pkg/controller/clusterissuers/controller.go b/pkg/controller/clusterissuers/controller.go index 49bcce1bb..d2ebd8326 100644 --- a/pkg/controller/clusterissuers/controller.go +++ b/pkg/controller/clusterissuers/controller.go @@ -190,7 +190,7 @@ const ( ) func init() { - controllerpkg.Register(ControllerName, func(ctx *controllerpkg.Context) controllerpkg.Interface { - return New(ctx).Run + controllerpkg.Register(ControllerName, func(ctx *controllerpkg.Context) (controllerpkg.Interface, error) { + return New(ctx).Run, nil }) } diff --git a/pkg/controller/context.go b/pkg/controller/context.go index 259cd011e..62e76ece7 100644 --- a/pkg/controller/context.go +++ b/pkg/controller/context.go @@ -23,6 +23,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" kubeinformers "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" "k8s.io/client-go/tools/record" clientset "github.com/jetstack/cert-manager/pkg/client/clientset/versioned" @@ -37,6 +38,11 @@ type Context struct { // RootContext is the root context for the controller RootContext context.Context + // StopCh is a channel that will be closed when the controller is signalled + // to exit + StopCh <-chan struct{} + // RESTConfig is the loaded Kubernetes apiserver rest client configuration + RESTConfig *rest.Config // Client is a Kubernetes clientset Client kubernetes.Interface // CMClient is a cert-manager clientset diff --git a/pkg/controller/ingress-shim/controller.go b/pkg/controller/ingress-shim/controller.go index e09744f40..424afd9e6 100644 --- a/pkg/controller/ingress-shim/controller.go +++ b/pkg/controller/ingress-shim/controller.go @@ -212,7 +212,7 @@ func (c *Controller) processNextWorkItem(ctx context.Context, key string) error var keyFunc = controllerpkg.KeyFunc func init() { - controllerpkg.Register(ControllerName, func(ctx *controllerpkg.Context) controllerpkg.Interface { + controllerpkg.Register(ControllerName, func(ctx *controllerpkg.Context) (controllerpkg.Interface, error) { var clusterIssuerInformer cminformers.ClusterIssuerInformer if ctx.Namespace == "" { clusterIssuerInformer = ctx.SharedInformerFactory.Certmanager().V1alpha1().ClusterIssuers() @@ -226,6 +226,6 @@ func init() { ctx.CMClient, ctx.Recorder, defaults{ctx.DefaultAutoCertificateAnnotations, ctx.DefaultIssuerName, ctx.DefaultIssuerKind, ctx.DefaultACMEIssuerChallengeType, ctx.DefaultACMEIssuerDNS01ProviderName}, - ).Run + ).Run, nil }) } diff --git a/pkg/controller/issuers/controller.go b/pkg/controller/issuers/controller.go index c80ae08d0..f27db5e3e 100644 --- a/pkg/controller/issuers/controller.go +++ b/pkg/controller/issuers/controller.go @@ -192,7 +192,7 @@ const ( ) func init() { - controllerpkg.Register(ControllerName, func(ctx *controllerpkg.Context) controllerpkg.Interface { - return New(ctx).Run + controllerpkg.Register(ControllerName, func(ctx *controllerpkg.Context) (controllerpkg.Interface, error) { + return New(ctx).Run, nil }) } diff --git a/pkg/controller/register.go b/pkg/controller/register.go index 39ef292cb..7ce1de404 100644 --- a/pkg/controller/register.go +++ b/pkg/controller/register.go @@ -28,7 +28,7 @@ type Interface func(workers int, stopCh <-chan struct{}) error // Constructor is a function that creates a new control loop given a // controller Context. -type Constructor func(ctx *Context) Interface +type Constructor func(ctx *Context) (Interface, error) var ( known = make(map[string]Constructor, 0)