func locateReplicaField(document openapi.Resources, res *unstructured.Unstructured) bool {
	replicaFieldPath := []string{"spec", "replicas"}
	gv, err := schema.ParseGroupVersion(res.GetAPIVersion())
	if err != nil {
		return false
	}
	schema := document.LookupResource(schema.GroupVersionKind{
		Group:   gv.Group,
		Version: gv.Version,
		Kind:    res.GetKind(),
	})
	field, err := explain.LookupSchemaForField(schema, replicaFieldPath)
	if err != nil || field == nil {
		return false
	}
	replicaField, ok := field.(*proto.Primitive)
	if !ok || replicaField.Type != "integer" {
		return false
	}
	return true
}
locateReplicaField call openapi RESTFUL end point to fetch the schema of a given resource and try to see
if it has a spec.replicas filed that is of type integer. We will apply duck typing to modify the fields there
assuming that the fields is used to control the number of instances of this resource
NOTE: This only works if the resource CRD has a structural schema, all `apiextensions.k8s.io/v1` CRDs do
https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema
package manualscalertrait
import (
	"context"
	"fmt"
	"strings"
	cpv1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
	"github.com/crossplane/crossplane-runtime/pkg/event"
	"github.com/crossplane/crossplane-runtime/pkg/logging"
	cpmeta "github.com/crossplane/crossplane-runtime/pkg/meta"
	"github.com/go-logr/logr"
	"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"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/client-go/discovery"
	"k8s.io/kube-openapi/pkg/util/proto"
	"k8s.io/kubectl/pkg/explain"
	"k8s.io/kubectl/pkg/util/openapi"
	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"
	oamv1alpha2 "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/discoverymapper"
	"github.com/crossplane/oam-kubernetes-runtime/pkg/oam/util"
)
const (
	errQueryOpenAPI            = "failed to query openAPI"
	errPatchTobeScaledResource = "cannot patch the resource for scale"
	errScaleResource           = "cannot scale the resource"
)
func Setup(mgr ctrl.Manager, args controller.Args, log logging.Logger) error {
	dm, err := discoverymapper.New(mgr.GetConfig())
	if err != nil {
		return err
	}
	reconciler := Reconciler{
		Client:          mgr.GetClient(),
		DiscoveryClient: *discovery.NewDiscoveryClientForConfigOrDie(mgr.GetConfig()),
		dm:              dm,
		log:             ctrl.Log.WithName("ManualScalarTrait"),
		record:          event.NewAPIRecorder(mgr.GetEventRecorderFor("ManualScalarTrait")),
		Scheme:          mgr.GetScheme(),
	}
	return reconciler.SetupWithManager(mgr)
}
type Reconciler struct {
	client.Client
	discovery.DiscoveryClient
	dm     discoverymapper.DiscoveryMapper
	log    logr.Logger
	record event.Recorder
	Scheme *runtime.Scheme
}
func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
	ctx := context.Background()
	mLog := r.log.WithValues("manualscalar trait", req.NamespacedName)
	mLog.Info("Reconcile manualscalar trait")
	var manualScalar oamv1alpha2.ManualScalerTrait
	if err := r.Get(ctx, req.NamespacedName, &manualScalar); err != nil {
		return ctrl.Result{}, client.IgnoreNotFound(err)
	}
	r.log.Info("Get the manualscalar trait", "ReplicaCount", manualScalar.Spec.ReplicaCount,
		"Annotations", manualScalar.GetAnnotations())
	eventObj, err := util.LocateParentAppConfig(ctx, r.Client, &manualScalar)
	if eventObj == nil {
		mLog.Error(err, "Failed to find the parent resource", "manualScalar", manualScalar.Name)
		eventObj = &manualScalar
	}
	workload, err := util.FetchWorkload(ctx, r, mLog, &manualScalar)
	if err != nil {
		r.record.Event(eventObj, event.Warning(util.ErrLocateWorkload, err))
		return util.ReconcileWaitResult, util.PatchCondition(
			ctx, r, &manualScalar, cpv1alpha1.ReconcileError(errors.Wrap(err, util.ErrLocateWorkload)))
	}
	resources, err := util.FetchWorkloadChildResources(ctx, mLog, r, r.dm, workload)
	if err != nil {
		mLog.Error(err, "Error while fetching the workload child resources", "workload", workload.UnstructuredContent())
		r.record.Event(eventObj, event.Warning(util.ErrFetchChildResources, err))
		return util.ReconcileWaitResult, util.PatchCondition(ctx, r, &manualScalar,
			cpv1alpha1.ReconcileError(fmt.Errorf(util.ErrFetchChildResources)))
	}
	if len(resources) == 0 {
		resources = append(resources, workload)
	}
	result, err := r.scaleResources(ctx, mLog, manualScalar, resources)
	if err != nil {
		r.record.Event(eventObj, event.Warning(errScaleResource, err))
		return result, err
	}
	r.record.Event(eventObj, event.Normal("Manual scalar applied",
		fmt.Sprintf("Trait `%s` successfully scaled a resource to %d instances",
			manualScalar.Name, manualScalar.Spec.ReplicaCount)))
	return ctrl.Result{}, util.PatchCondition(ctx, r, &manualScalar, cpv1alpha1.ReconcileSuccess())
}
func (r *Reconciler) scaleResources(ctx context.Context, mLog logr.Logger,
	manualScalar oamv1alpha2.ManualScalerTrait, resources []*unstructured.Unstructured) (ctrl.Result, error) {
	isController := false
	bod := true
	found := false
	ownerRef := metav1.OwnerReference{
		APIVersion:         manualScalar.APIVersion,
		Kind:               manualScalar.Kind,
		Name:               manualScalar.Name,
		UID:                manualScalar.UID,
		Controller:         &isController,
		BlockOwnerDeletion: &bod,
	}
	schemaDoc, err := r.DiscoveryClient.OpenAPISchema()
	if err != nil {
		return util.ReconcileWaitResult,
			util.PatchCondition(ctx, r, &manualScalar, cpv1alpha1.ReconcileError(errors.Wrap(err, errQueryOpenAPI)))
	}
	document, err := openapi.NewOpenAPIData(schemaDoc)
	if err != nil {
		return util.ReconcileWaitResult,
			util.PatchCondition(ctx, r, &manualScalar, cpv1alpha1.ReconcileError(errors.Wrap(err, errQueryOpenAPI)))
	}
	for _, res := range resources {
		if locateReplicaField(document, res) {
			found = true
			resPatch := client.MergeFrom(res.DeepCopyObject())
			mLog.Info("Get the resource the trait is going to modify",
				"resource name", res.GetName(), "UID", res.GetUID())
			cpmeta.AddOwnerReference(res, ownerRef)
			err := unstructured.SetNestedField(res.Object, int64(manualScalar.Spec.ReplicaCount), "spec", "replicas")
			if err != nil {
				mLog.Error(err, "Failed to patch a resource for scaling")
				return util.ReconcileWaitResult,
					util.PatchCondition(ctx, r, &manualScalar, cpv1alpha1.ReconcileError(errors.Wrap(err, errPatchTobeScaledResource)))
			}
			if err := r.Patch(ctx, res, resPatch, client.FieldOwner(manualScalar.GetUID())); err != nil {
				mLog.Error(err, "Failed to scale a resource")
				return util.ReconcileWaitResult,
					util.PatchCondition(ctx, r, &manualScalar, cpv1alpha1.ReconcileError(errors.Wrap(err, errScaleResource)))
			}
			mLog.Info("Successfully scaled a resource", "resource GVK", res.GroupVersionKind().String(),
				"res UID", res.GetUID(), "target replica", manualScalar.Spec.ReplicaCount)
		}
	}
	if !found {
		mLog.Info("Cannot locate any resource", "total resources", len(resources))
		return util.ReconcileWaitResult,
			util.PatchCondition(ctx, r, &manualScalar, cpv1alpha1.ReconcileError(fmt.Errorf(errScaleResource)))
	}
	return ctrl.Result{}, nil
}