func WithGarbageCollector(gc GarbageCollector) ReconcilerOption {
	return func(rc *OAMApplicationReconciler) {
		rc.gc = gc
	}
}
WithGarbageCollector specifies how the Reconciler should garbage collect
workloads and traits when an ApplicationConfiguration is edited to remove
them.
package applicationconfiguration
import (
	"context"
	"fmt"
	"strconv"
	"strings"
	"time"
	"github.com/pkg/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime"
	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/reconcile"
	"sigs.k8s.io/controller-runtime/pkg/source"
	"github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
	runtimev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
	"github.com/crossplane/crossplane-runtime/pkg/event"
	"github.com/crossplane/crossplane-runtime/pkg/logging"
	"github.com/crossplane/crossplane-runtime/pkg/meta"
	"github.com/crossplane/crossplane-runtime/pkg/resource"
	"github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
	"github.com/crossplane/oam-kubernetes-runtime/pkg/controller"
	"github.com/crossplane/oam-kubernetes-runtime/pkg/oam"
	"github.com/crossplane/oam-kubernetes-runtime/pkg/oam/discoverymapper"
	"github.com/crossplane/oam-kubernetes-runtime/pkg/oam/util"
)
const (
	reconcileTimeout = 1 * time.Minute
	dependCheckWait  = 10 * time.Second
	shortWait        = 30 * time.Second
)
const (
	errGetAppConfig          = "cannot get application configuration"
	errUpdateAppConfigStatus = "cannot update application configuration status"
	errExecutePrehooks       = "failed to execute pre-hooks"
	errExecutePosthooks      = "failed to execute post-hooks"
	errRenderComponents      = "cannot render components"
	errApplyComponents       = "cannot apply components"
	errGCComponent           = "cannot garbage collect components"
	errFinalizeWorkloads     = "failed to finalize workloads"
)
const (
	reasonRenderComponents        = "RenderedComponents"
	reasonExecutePrehook          = "ExecutePrehook"
	reasonExecutePosthook         = "ExecutePosthook"
	reasonApplyComponents         = "AppliedComponents"
	reasonGGComponent             = "GarbageCollectedComponent"
	reasonCannotExecutePrehooks   = "CannotExecutePrehooks"
	reasonCannotExecutePosthooks  = "CannotExecutePosthooks"
	reasonCannotRenderComponents  = "CannotRenderComponents"
	reasonCannotApplyComponents   = "CannotApplyComponents"
	reasonCannotGGComponents      = "CannotGarbageCollectComponents"
	reasonCannotFinalizeWorkloads = "CannotFinalizeWorkloads"
)
func Setup(mgr ctrl.Manager, args controller.Args, l logging.Logger) error {
	dm, err := discoverymapper.New(mgr.GetConfig())
	if err != nil {
		return fmt.Errorf("create discovery dm fail %v", err)
	}
	name := "oam/" + strings.ToLower(v1alpha2.ApplicationConfigurationGroupKind)
	return ctrl.NewControllerManagedBy(mgr).
		Named(name).
		For(&v1alpha2.ApplicationConfiguration{}).
		Watches(&source.Kind{Type: &v1alpha2.Component{}}, &ComponentHandler{
			Client:        mgr.GetClient(),
			Logger:        l,
			RevisionLimit: args.RevisionLimit,
		}).
		Complete(NewReconciler(mgr, dm,
			WithLogger(l.WithValues("controller", name)),
			WithRecorder(event.NewAPIRecorder(mgr.GetEventRecorderFor(name))),
			WithApplyOnceOnly(args.ApplyOnceOnly),
			WithLogWaitTime(args.LongWait)))
}
type OAMApplicationReconciler struct {
	client        client.Client
	components    ComponentRenderer
	workloads     WorkloadApplicator
	gc            GarbageCollector
	scheme        *runtime.Scheme
	log           logging.Logger
	record        event.Recorder
	preHooks      map[string]ControllerHooks
	postHooks     map[string]ControllerHooks
	applyOnceOnly bool
	longWait      time.Duration
}
type ReconcilerOption func(*OAMApplicationReconciler)
func WithRenderer(r ComponentRenderer) ReconcilerOption {
	return func(rc *OAMApplicationReconciler) {
		rc.components = r
	}
}
func WithApplicator(a WorkloadApplicator) ReconcilerOption {
	return func(rc *OAMApplicationReconciler) {
		rc.workloads = a
	}
}