func (r *XDLJobReconciler) GetDefaultContainerPortNumber() int32 {
	return xdlv1alpha1.XDLJobDefaultPort
}
GetDefaultContainerPortNumber get the default container port number
package xdljob
import (
	"context"
	"fmt"
	"strings"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/client-go/tools/record"
	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/controller"
	"sigs.k8s.io/controller-runtime/pkg/handler"
	"sigs.k8s.io/controller-runtime/pkg/manager"
	"sigs.k8s.io/controller-runtime/pkg/predicate"
	"sigs.k8s.io/controller-runtime/pkg/reconcile"
	logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
	"sigs.k8s.io/controller-runtime/pkg/source"
	xdlv1alpha1 "github.com/alibaba/kubedl/apis/training/v1alpha1"
	"github.com/alibaba/kubedl/cmd/options"
	"github.com/alibaba/kubedl/pkg/gang_schedule/registry"
	"github.com/alibaba/kubedl/pkg/job_controller"
	v1 "github.com/alibaba/kubedl/pkg/job_controller/api/v1"
	"github.com/alibaba/kubedl/pkg/metrics"
	"github.com/alibaba/kubedl/pkg/util"
)
const (
	controllerName = "XDLController"
)
const (
	xdlConfig = "XDL_CONFIG"
	taskType  = "TASK_NAME"
	taskIndex = "TASK_INDEX"
	zkAddr    = "ZK_ADDR"
)
var log = logf.Log.WithName("xdl-controller")
func NewReconciler(mgr manager.Manager, config options.JobControllerConfiguration) *XDLJobReconciler {
	r := &XDLJobReconciler{
		Client: mgr.GetClient(),
		scheme: mgr.GetScheme(),
	}
	r.recorder = mgr.GetEventRecorderFor(r.ControllerName())
	r.ctrl = job_controller.NewJobController(r.Client, r, config, r.recorder, metrics.NewJobMetrics(xdlv1alpha1.XDLJobKind, r.Client))
	if r.ctrl.Config.EnableGangScheduling {
		r.ctrl.GangScheduler = registry.Get(r.ctrl.Config.GangSchedulerName)
	}
	return r
}
var _ reconcile.Reconciler = &XDLJobReconciler{}
var _ v1.ControllerInterface = &XDLJobReconciler{}
type XDLJobReconciler struct {
	client.Client
	scheme   *runtime.Scheme
	recorder record.EventRecorder
	ctrl     job_controller.JobController
}
func (r *XDLJobReconciler) Reconcile(request reconcile.Request) (reconcile.Result, error) {
	sharedXdlJob := &xdlv1alpha1.XDLJob{}
	err := util.GetObjectByPassCache(r.Client, request.NamespacedName, sharedXdlJob)
	if err != nil {
		if errors.IsNotFound(err) {
			log.Info("try to get job but it has been deleted", "key", request.String())
			r.ctrl.Metrics.DeletedInc()
			return reconcile.Result{}, nil
		}
		return reconcile.Result{}, err
	}
	xdlJob := sharedXdlJob.DeepCopy()
	needSync := r.ctrl.SatisfyExpectations(xdlJob, xdlJob.Spec.XDLReplicaSpecs)
	if !needSync || xdlJob.DeletionTimestamp != nil {
		log.Info("reconcile cancelled, job does not need to do reconcile or has been deleted",
			"sync", needSync, "deleted", xdlJob.DeletionTimestamp != nil)
		return reconcile.Result{}, nil
	}
	r.scheme.Default(xdlJob)
	result, err := r.ctrl.ReconcileJobs(xdlJob, xdlJob.Spec.XDLReplicaSpecs, xdlJob.Status, &xdlJob.Spec.RunPolicy, nil)
	if err != nil {
		log.Error(err, "xdl job reconcile failed.")
		return result, err
	}
	return result, err
}
func (r *XDLJobReconciler) SetupWithManager(mgr ctrl.Manager) error {
	c, err := controller.New(r.ControllerName(), mgr, controller.Options{
		Reconciler:              r,
		MaxConcurrentReconciles: options.CtrlConfig.MaxConcurrentReconciles,
	})
	if err != nil {
		return err
	}
	if err = c.Watch(&source.Kind{Type: &xdlv1alpha1.XDLJob{}}, &handler.EnqueueRequestForObject{}, predicate.Funcs{
		CreateFunc: onOwnerCreateFunc(r),
	}); err != nil {
		return err
	}
	if err = c.Watch(&source.Kind{Type: &corev1.Pod{}}, &handler.EnqueueRequestForOwner{
		OwnerType:    &xdlv1alpha1.XDLJob{},
		IsController: true,
	}, predicate.Funcs{
		CreateFunc: r.ctrl.OnPodCreateFunc,
		UpdateFunc: r.ctrl.OnPodUpdateFunc,
		DeleteFunc: r.ctrl.OnPodDeleteFunc,
	}); err != nil {
		return err
	}
	return c.Watch(&source.Kind{Type: &corev1.Service{}}, &handler.EnqueueRequestForOwner{
		OwnerType:    &xdlv1alpha1.XDLJob{},
		IsController: true,
	}, predicate.Funcs{
		CreateFunc: r.ctrl.OnServiceCreateFunc,
		UpdateFunc: r.ctrl.OnServiceUpdateFunc,
		DeleteFunc: r.ctrl.OnServiceDeleteFunc,
	})
}
func (r *XDLJobReconciler) ControllerName() string {
	return controllerName
}
func (r *XDLJobReconciler) GetAPIGroupVersionKind() schema.GroupVersionKind {
	return xdlv1alpha1.SchemeGroupVersion.WithKind(xdlv1alpha1.XDLJobKind)
}
func (r *XDLJobReconciler) GetAPIGroupVersion() schema.GroupVersion {
	return xdlv1alpha1.SchemeGroupVersion
}
func (r *XDLJobReconciler) GetGroupNameLabelValue() string {
	return r.GetAPIGroupVersion().Group
}
func (r *XDLJobReconciler) SetClusterSpec(ctx context.Context, job interface{}, podTemplate *corev1.PodTemplateSpec, rtype, index string) error {
	xdlJob, ok := job.(*xdlv1alpha1.XDLJob)
	if !ok {
		return fmt.Errorf("%+v is not a type of XDLJob", job)
	}
	for i := range podTemplate.Spec.Containers {
		container := &podTemplate.Spec.Containers[i]
		if len(container.Env) == 0 {
			container.Env = make([]corev1.EnvVar, 0)
		}
		for j := range container.Env {
			env := &container.Env[j]
			if env.Name == zkAddr {
				if strings.HasSuffix(env.Value, "/") {
					env.Value += string(xdlJob.UID)
				} else {
					env.Value += "/" + string(xdlJob.UID)
				}
			}
		}
		container.Env = append(container.Env,
			corev1.EnvVar{Name: taskType, Value: strings.ToLower(rtype)},
			corev1.EnvVar{Name: taskIndex, Value: index})
	}
	return nil
}
func (r *XDLJobReconciler) GetDefaultContainerName() string {
	return xdlv1alpha1.XDLJobDefaultContainerName
}
func (r *XDLJobReconciler) GetDefaultContainerPortName() string {
	return xdlv1alpha1.XDLJobDefaultContainerPortName
}