func (a *OpenAPI) DescribeNetworkInterface(ctx context.Context, vpcID string, eniID []string, instanceID string, instanceType ENIType, status ENIStatus) ([]ecs.NetworkInterfaceSet, error) {
	var result []ecs.NetworkInterfaceSet
	for i := 1; ; {
		req := ecs.CreateDescribeNetworkInterfacesRequest()
		req.VpcId = vpcID
		req.NetworkInterfaceId = &eniID
		req.InstanceId = instanceID
		req.Type = string(instanceType)
		req.Status = string(status)
		req.PageNumber = requests.NewInteger(i)
		req.PageSize = requests.NewInteger(maxSinglePageSize)
		l := log.WithFields(map[string]interface{}{
			LogFieldAPI:        "DescribeNetworkInterfaces",
			LogFieldENIID:      eniID,
			LogFieldInstanceID: instanceID,
		})
		a.ReadOnlyRateLimiter.Accept()
		start := time.Now()
		resp, err := a.ClientSet.ECS().DescribeNetworkInterfaces(req)
		metric.OpenAPILatency.WithLabelValues("DescribeNetworkInterfaces", fmt.Sprint(err != nil)).Observe(metric.MsSince(start))
		if err != nil {
			l.WithField(LogFieldRequestID, apiErr.ErrRequestID(err)).Warn(err)
			return nil, err
		}
		result = append(result, resp.NetworkInterfaceSets.NetworkInterfaceSet...)
		if resp.TotalCount < resp.PageNumber*resp.PageSize {
			break
		}
		i++
	}
	return result, nil
}
DescribeNetworkInterface list eni
package aliyun
import (
	"context"
	"fmt"
	"net"
	"time"
	apiErr "github.com/AliyunContainerService/terway/pkg/aliyun/errors"
	"github.com/AliyunContainerService/terway/pkg/ip"
	"github.com/AliyunContainerService/terway/pkg/metric"
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
	"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/util/flowcontrol"
)
const maxSinglePageSize = 100
type OpenAPI struct {
	ClientSet *ClientMgr
	ReadOnlyRateLimiter flowcontrol.RateLimiter
	MutatingRateLimiter flowcontrol.RateLimiter
}
func NewAliyun(ak, sk, regionID, credentialPath string) (*OpenAPI, error) {
	if regionID == "" {
		return nil, fmt.Errorf("regionID unset")
	}
	clientSet, err := NewClientMgr(ak, sk, credentialPath, regionID)
	if err != nil {
		return nil, fmt.Errorf("error get clientset, %w", err)
	}
	return &OpenAPI{
		ClientSet:           clientSet,
		ReadOnlyRateLimiter: flowcontrol.NewTokenBucketRateLimiter(8, 10),
		MutatingRateLimiter: flowcontrol.NewTokenBucketRateLimiter(4, 5),
	}, nil
}
func (a *OpenAPI) CreateNetworkInterface(ctx context.Context, instanceType ENIType, vSwitch string, securityGroups []string, ipCount, ipv6Count int, eniTags map[string]string) (*ecs.CreateNetworkInterfaceResponse, error) {
	req := ecs.CreateCreateNetworkInterfaceRequest()
	req.VSwitchId = vSwitch
	req.InstanceType = string(instanceType)
	req.SecurityGroupIds = &securityGroups
	req.NetworkInterfaceName = generateEniName()
	req.Description = eniDescription
	if ipCount > 1 {
		req.SecondaryPrivateIpAddressCount = requests.NewInteger(ipCount - 1)
	}
	if ipv6Count > 0 {
		req.Ipv6AddressCount = requests.NewInteger(ipv6Count)
	}
	var tags []ecs.CreateNetworkInterfaceTag
	for k, v := range eniTags {
		tags = append(tags, ecs.CreateNetworkInterfaceTag{
			Key:   k,
			Value: v,
		})
	}
	req.Tag = &tags
	l := log.WithFields(map[string]interface{}{
		LogFieldAPI:       "CreateNetworkInterface",
		LogFieldVSwitchID: vSwitch,
	})
	a.MutatingRateLimiter.Accept()
	start := time.Now()
	resp, err := a.ClientSet.ECS().CreateNetworkInterface(req)
	metric.OpenAPILatency.WithLabelValues("CreateNetworkInterface", fmt.Sprint(err != nil)).Observe(metric.MsSince(start))
	if err != nil {
		l.WithField(LogFieldRequestID, apiErr.ErrRequestID(err)).Errorf("error create ENI, %s", err.Error())
		return nil, err
	}
	l.WithFields(map[string]interface{}{
		LogFieldENIID:     resp.NetworkInterfaceId,
		LogFieldRequestID: resp.RequestId,
	}).Info("create ENI")
	return resp, err
}