Create a controller

You can use the sample repository update-codegen.sh script to generate and inject the required components (the clientset, cache, informers, and listers) into your custom controller.

Example controller:

  1. import (
  2. // ...
  3. sampleSourceClient "knative.dev/sample-source/pkg/client/injection/client"
  4. samplesourceinformer "knative.dev/sample-source/pkg/client/injection/informers/samples/v1alpha1/samplesource"
  5. )
  6. // ...
  7. func NewController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
  8. sampleSourceInformer := samplesourceinformer.Get(ctx)
  9. r := &Reconciler{
  10. // ...
  11. samplesourceClientSet: sampleSourceClient.Get(ctx),
  12. samplesourceLister: sampleSourceInformer.Lister(),
  13. // ...
  14. }

Procedure

  1. Generate the components by running the command:

    1. ${CODEGEN_PKG}/generate-groups.sh "deepcopy,client,informer,lister" \
    2. knative.dev/sample-source/pkg/client knative.dev/sample-source/pkg/apis \
    3. "samples:v1alpha1" \
    4. --go-header-file ${REPO_ROOT}/hack/boilerplate/boilerplate.go.txt
  2. Inject the components by running the command:

    1. # Injection
    2. ${KNATIVE_CODEGEN_PKG}/hack/generate-knative.sh "injection" \
    3. knative.dev/sample-source/pkg/client knative.dev/sample-source/pkg/apis \
    4. "samples:v1alpha1" \
    5. --go-header-file ${REPO_ROOT}/hack/boilerplate/boilerplate.go.txt
  3. Pass the new controller implementation to the sharedmain method:

    1. import (
    2. // The set of controllers this controller process runs.
    3. "knative.dev/sample-source/pkg/reconciler/sample"
    4. // This defines the shared main for injected controllers.
    5. "knative.dev/pkg/injection/sharedmain"
    6. )
    7. func main() {
    8. sharedmain.Main("sample-source-controller", sample.NewController)
    9. }
  4. Define the NewController implementation:

    1. func NewController(
    2. ctx context.Context,
    3. cmw configmap.Watcher,
    4. ) *controller.Impl {
    5. // ...
    6. deploymentInformer := deploymentinformer.Get(ctx)
    7. sinkBindingInformer := sinkbindinginformer.Get(ctx)
    8. sampleSourceInformer := samplesourceinformer.Get(ctx)
    9. r := &Reconciler{
    10. dr: &reconciler.DeploymentReconciler{KubeClientSet: kubeclient.Get(ctx)},
    11. sbr: &reconciler.SinkBindingReconciler{EventingClientSet: eventingclient.Get(ctx)},
    12. // Config accessor takes care of tracing/config/logging config propagation to the receive adapter
    13. configAccessor: reconcilersource.WatchConfigurations(ctx, "sample-source", cmw),
    14. }

    A configmap.Watcher and a context, which the injected listers use for the reconciler struct arguments, are passed to this implementation.

  5. Import the base reconciler from the knative.dev/pkg dependency:

    1. import (
    2. // ...
    3. reconcilersource "knative.dev/eventing/pkg/reconciler/source"
    4. // ...
    5. )
  6. Ensure that the event handlers are being filtered to the correct informers:

    1. sampleSourceInformer.Informer().AddEventHandler(controller.HandleAll(impl.Enqueue))
  7. Ensure that informers are configured correctly for the secondary resources used by the sample source to deploy and bind the event source and the receive adapter:

    1. deploymentInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{
    2. FilterFunc: controller.FilterGroupKind(v1alpha1.Kind("SampleSource")),
    3. Handler: controller.HandleAll(impl.EnqueueControllerOf),
    4. })
    5. sinkBindingInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{
    6. FilterFunc: controller.FilterGroupKind(v1alpha1.Kind("SampleSource")),
    7. Handler: controller.HandleAll(impl.EnqueueControllerOf),
    8. })