func (m *ReconcilePod) podCreate(ctx context.Context, pod *corev1.Pod) (r reconcile.Result, err error) {
	l := log.FromContext(ctx)
	prePodENI := &v1beta1.PodENI{}
	err = m.client.Get(ctx, k8stypes.NamespacedName{
		Namespace: pod.Namespace,
		Name:      pod.Name,
	}, prePodENI)
	if err == nil {
		if !prePodENI.DeletionTimestamp.IsZero() {
			return reconcile.Result{Requeue: true}, nil
		}
		switch prePodENI.Status.Status {
		case v1beta1.ENIStatusUnbind:
			prePodENICopy := prePodENI.DeepCopy()
			prePodENICopy.Status.Status = v1beta1.ENIStatusBinding
			_, err = common.SetPodENIStatus(ctx, m.client, prePodENICopy, prePodENI)
			return reconcile.Result{}, err
		case v1beta1.ENIStatusBind:
			return reconcile.Result{}, nil
		}
		return reconcile.Result{Requeue: true}, nil
	}
	l.Info("creating eni")
	podENI := &v1beta1.PodENI{
		ObjectMeta: metav1.ObjectMeta{
			Name:      pod.Name,
			Namespace: pod.Namespace,
			Finalizers: []string{
				types.FinalizerPodENI,
			},
		},
	}
	defer func() {
		if err != nil {
			l.WithValues("eni", "").Error(err, "create fail")
			m.record.Eventf(podENI, corev1.EventTypeWarning, types.EventCreateENIFailed, err.Error())
		} else {
			l.WithValues("eni", podENI.Spec.Allocation.ENI.ID).Info("create")
			m.record.Eventf(podENI, corev1.EventTypeNormal, types.EventCreateENISucceed, "create eni %s", podENI.Spec.Allocation.ENI.ID)
		}
	}()
	podConf := &common.PodConf{}
	node, err := m.getNode(ctx, pod.Spec.NodeName)
	if err != nil {
		e := fmt.Errorf("error get node %s, %w", node.Name, err)
		return reconcile.Result{}, e
	}
	err = podConf.SetNodeConf(node)
	if err != nil {
		e := fmt.Errorf("error parse config from node %s, %w", node.Name, err)
		return reconcile.Result{}, e
	}
	podNetwokingName := pod.Annotations[types.PodNetworking]
	podNetworking := &v1beta1.PodNetworking{}
	err = m.client.Get(ctx, k8stypes.NamespacedName{
		Name: podNetwokingName,
	}, podNetworking)
	if err != nil {
		return reconcile.Result{}, fmt.Errorf("error get podNetworking %s, %w", podNetwokingName, err)
	}
	err = podConf.SetPodNetworkingConf(podNetworking)
	if err != nil {
		return reconcile.Result{}, fmt.Errorf("error parse podNetworking %s, %w", podNetwokingName, err)
	}
	vsw, err := m.swPool.GetOne(podConf.Zone, sets.NewString(podNetworking.Spec.VSwitchIDs...))
	if err != nil {
		return reconcile.Result{}, fmt.Errorf("can not found available vSwitch for zone %s, %w", podConf.Zone, err)
	}
	podConf.VSwitchID = vsw
	eni, err := m.aliyun.CreateNetworkInterface(context.Background(), aliyun.ENITypeSecondary, podConf.VSwitchID, podConf.SecurityGroups, 1, 0, map[string]string{
		types.TagKeyClusterID:               viper.GetString("cluster-id"),
		types.NetworkInterfaceTagCreatorKey: types.TagTerwayController,
		types.TagKubernetesPodName:          utils.TrimStr(pod.Name, 120),
		types.TagKubernetesPodNamespace:     utils.TrimStr(pod.Namespace, 120),
	})
	if err != nil {
		return reconcile.Result{}, fmt.Errorf("create eni with openAPI err, %w", err)
	}
	podENI.Spec.Allocation = v1beta1.Allocation{
		ENI: v1beta1.ENI{
			ID:   eni.NetworkInterfaceId,
			MAC:  eni.MacAddress,
			Zone: eni.ZoneId,
		},
		IPv4: eni.PrivateIpAddress,
		IPv6: "",
		IPType: v1beta1.IPType{
			Type:            podConf.IPAllocType,
			ReleaseStrategy: podConf.ReleaseStrategy,
			ReleaseAfter:    podConf.FixedIPReleaseAfter.String(),
		},
	}
	defer func() {
		if err != nil {
			innerErr := m.deleteMemberENI(podENI)
			if innerErr != nil {
				l.Error(innerErr, "error delete eni %w")
			}
		}
	}()
	err = m.client.Create(ctx, podENI)
	if err != nil {
		return reconcile.Result{}, fmt.Errorf("error create cr, %s", err)
	}
	return reconcile.Result{}, nil
}
podCreate is the func when the pod is to be create or created
package pod
import (
	"context"
	"fmt"
	"time"
	"github.com/AliyunContainerService/terway/pkg/aliyun"
	"github.com/AliyunContainerService/terway/pkg/apis/network.alibabacloud.com/v1beta1"
	register "github.com/AliyunContainerService/terway/pkg/controller"
	"github.com/AliyunContainerService/terway/pkg/controller/common"
	"github.com/AliyunContainerService/terway/pkg/controller/vswitch"
	"github.com/AliyunContainerService/terway/pkg/utils"
	"github.com/AliyunContainerService/terway/types"
	"github.com/spf13/viper"
	corev1 "k8s.io/api/core/v1"
	k8sErr "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	k8stypes "k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/client-go/tools/record"
	"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/log"
	"sigs.k8s.io/controller-runtime/pkg/manager"
	"sigs.k8s.io/controller-runtime/pkg/predicate"
	"sigs.k8s.io/controller-runtime/pkg/reconcile"
	"sigs.k8s.io/controller-runtime/pkg/source"
)
const controllerName = "pod"
func init() {
	register.Add(controllerName, func(mgr manager.Manager, aliyunClient *aliyun.OpenAPI, swPool *vswitch.SwitchPool) error {
		r := NewReconcilePod(mgr, aliyunClient, swPool)
		c, err := controller.NewUnmanaged(controllerName, mgr, controller.Options{
			Reconciler:              r,
			MaxConcurrentReconciles: viper.GetInt("podeni-max-concurrent-reconciles"),
		})
		if err != nil {
			return err
		}
		w := &Wrapper{
			ctrl: c,
			r:    r,
		}
		err = mgr.Add(w)
		if err != nil {
			return err
		}
		return c.Watch(
			&source.Kind{
				Type: &corev1.Pod{},
			},
			&handler.EnqueueRequestForObject{},
			&predicate.ResourceVersionChangedPredicate{},
			&predicateForPodEvent{},
		)
	})
}
var _ reconcile.Reconciler = &ReconcilePod{}
type ReconcilePod struct {
	client client.Client
	scheme *runtime.Scheme
	aliyun *aliyun.OpenAPI
	swPool *vswitch.SwitchPool
	record record.EventRecorder
}
type Wrapper struct {
	ctrl controller.Controller
	r    *ReconcilePod
}
func (w *Wrapper) Start(ctx context.Context) error {
	err := w.ctrl.Start(ctx)
	if err != nil {
		return err
	}
	<-ctx.Done()
	return nil
}
func (w *Wrapper) NeedLeaderElection() bool {
	return true
}
func NewReconcilePod(mgr manager.Manager, aliyunClient *aliyun.OpenAPI, swPool *vswitch.SwitchPool) *ReconcilePod {
	r := &ReconcilePod{
		client: mgr.GetClient(),
		scheme: mgr.GetScheme(),
		record: mgr.GetEventRecorderFor("Pod"),
		aliyun: aliyunClient,
		swPool: swPool,
	}
	return r
}
func (m *ReconcilePod) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
	l := log.FromContext(ctx)
	l.V(5).Info("Reconcile")
	pod := &corev1.Pod{}
	err := m.client.Get(context.Background(), request.NamespacedName, pod)
	if err != nil {
		if k8sErr.IsNotFound(err) {
			return m.podDelete(ctx, request.NamespacedName)
		}
		return reconcile.Result{}, err
	}
	if utils.IsJobPod(pod) {
		if utils.PodSandboxExited(pod) {
			return m.podDelete(ctx, request.NamespacedName)
		}
	}
	if !pod.DeletionTimestamp.IsZero() {
		return reconcile.Result{RequeueAfter: 2 * time.Second}, nil
	}
	return m.podCreate(ctx, pod)
}
func (m *ReconcilePod) NeedLeaderElection() bool {
	return true
}