func (c *ClusterConfig) newSubClusterBackend(ep *corev1.Endpoints, port intstr.IntOrString) cluster_table_conf.SubClusterBackend {
	if ep == nil {
		return nil
	}
	instanceList := make([]*cluster_table_conf.BackendConf, 0)
	if port.IntVal == 0 && len(port.StrVal) == 0 {
		if len(ep.Subsets) > 0 && len(ep.Subsets[0].Ports) > 0 && len(ep.Subsets[0].Addresses) > 0 {
			instanceList = append(instanceList, newBackendConf(ep.Subsets[0].Addresses[0].IP, int(ep.Subsets[0].Ports[0].Port), defaultWeight))
		}
		return instanceList
	}
	for _, subset := range ep.Subsets {
		for _, endpointPort := range subset.Ports {
			if port.IntVal == endpointPort.Port || port.StrVal == endpointPort.Name {
				for _, addr := range subset.Addresses {
					instanceList = append(instanceList, newBackendConf(addr.IP, int(endpointPort.Port), defaultWeight))
				}
			}
		}
	}
	return instanceList
}
newSubClusterBackend converts k8s service to bfe subCluster/instanceList
package configs
import (
	"fmt"
	corev1 "k8s.io/api/core/v1"
	netv1 "k8s.io/api/networking/v1"
	"k8s.io/apimachinery/pkg/util/intstr"
	ctrl "sigs.k8s.io/controller-runtime"
	"github.com/bfenetworks/bfe/bfe_config/bfe_cluster_conf/cluster_table_conf"
	"github.com/bfenetworks/bfe/bfe_config/bfe_cluster_conf/gslb_conf"
	"github.com/bfenetworks/ingress-bfe/internal/bfeConfig/annotations"
	"github.com/bfenetworks/ingress-bfe/internal/bfeConfig/util"
	"github.com/bfenetworks/ingress-bfe/internal/option"
	"github.com/jwangsadinata/go-multimap/setmultimap"
)
const (
	ConfigNameclusterConf = "gslb_data_conf"
	GslbData         = "cluster_conf/gslb.data"
	ClusterTableData = "cluster_conf/cluster_table.data"
)
var (
	log = ctrl.Log.WithName("configBuilder")
)
var (
	defaultWeight = 10
)
type ClusterConfig struct {
	gslbVersion         string  
	clusterTableVersion string
	ingress2Cluster *setmultimap.MultiMap
	service2Cluster *setmultimap.MultiMap
	gslbConf         gslb_conf.GslbConf
	clusterTableConf cluster_table_conf.ClusterTableConf
}
func NewClusterConfig(version string) *ClusterConfig {
	hostname := "bfe-ingress-controller"
	gslbCluster := make(gslb_conf.GslbClustersConf)
	clusterBackend := make(cluster_table_conf.AllClusterBackend)
	return &ClusterConfig{
		gslbVersion:         version,
		clusterTableVersion: version,
		ingress2Cluster:     setmultimap.New(),
		service2Cluster:     setmultimap.New(),
		gslbConf: gslb_conf.GslbConf{
			Clusters: &gslbCluster,
			Hostname: &hostname,
			Ts:       &version,
		},
		clusterTableConf: cluster_table_conf.ClusterTableConf{
			Version: &version,
			Config:  &clusterBackend,
		},
	}
}
func (c *ClusterConfig) setVersion() {
	version := util.NewVersion()
	c.gslbConf.Ts = &version
	c.clusterTableConf.Version = &version
}
func (c *ClusterConfig) UpdateIngress(ingress *netv1.Ingress, services map[string]*corev1.Service, endpoints map[string]*corev1.Endpoints) error {
	if len(ingress.Spec.Rules) == 0 {
		return nil
	}
	balance, _ := annotations.GetBalance(ingress.Annotations)
	ingressName := util.NamespacedName(ingress.Namespace, ingress.Name)
	for _, rule := range ingress.Spec.Rules {
		for _, path := range rule.HTTP.Paths {
			clusterName := util.ClusterName(ingressName, path.Backend.Service)
			(*c.clusterTableConf.Config)[clusterName] = c.newClusterBackend(ingress.Namespace, path.Backend.Service, balance, services, endpoints)
			(*c.gslbConf.Clusters)[clusterName] = c.newGslbClusterConf(ingress.Namespace, path.Backend.Service.Name, balance)
			c.ingress2Cluster.Put(ingressName, clusterName)
			for service := range (*c.gslbConf.Clusters)[clusterName] {
				c.service2Cluster.Put(service, clusterName)
			}
		}
	}
	if len(option.Opts.DefaultBackend) > 0 {
		c.addDefautBackend(endpoints[option.Opts.DefaultBackend])
	}
	if err := cluster_table_conf.ClusterTableConfCheck(c.clusterTableConf); err != nil {
		c.DeleteIngress(ingress.Namespace, ingress.Name)
		return err
	}
	c.setVersion()
	return nil
}
func (c *ClusterConfig) addDefautBackend(ep *corev1.Endpoints) {
	if ep == nil {
		return
	}
	if _, ok := (*c.clusterTableConf.Config)[util.DefaultClusterName()]; ok {
		return
	}
	instanceList := c.newSubClusterBackend(ep, intstr.IntOrString{})
	if len(instanceList) == 0 {
		return
	}
	serviceName := option.Opts.DefaultBackend
	subCluster := make(cluster_table_conf.ClusterBackend)
	subCluster[serviceName] = instanceList
	(*c.clusterTableConf.Config)[util.DefaultClusterName()] = subCluster
	gslbConf := make(gslb_conf.GslbClusterConf)
	gslbConf[serviceName] = defaultWeight
	(*c.gslbConf.Clusters)[util.DefaultClusterName()] = gslbConf
	c.service2Cluster.Put(serviceName, util.DefaultClusterName())
}
func (c *ClusterConfig) DeleteIngress(namespace, name string) {
	ingressName := util.NamespacedName(namespace, name)
	clusters, ok := c.ingress2Cluster.Get(ingressName)
	if !ok {
		return
	}
	for _, cluster := range clusters {
		clusterName := cluster.(string)
		for serviceName := range (*c.clusterTableConf.Config)[clusterName] {
			c.service2Cluster.Remove(serviceName, clusterName)
		}
		delete(*c.clusterTableConf.Config, clusterName)
		delete(*c.gslbConf.Clusters, clusterName)
	}
	c.ingress2Cluster.RemoveAll(ingressName)
	if len(option.Opts.DefaultBackend) > 0 && c.ingress2Cluster.Empty() {
		c.delDefautBackend()
	}
	c.setVersion()
}
func (c *ClusterConfig) delDefautBackend() {
	c.service2Cluster.Remove(option.Opts.DefaultBackend, util.DefaultClusterName())
	delete(*c.clusterTableConf.Config, util.DefaultClusterName())
	delete(*c.gslbConf.Clusters, util.DefaultClusterName())
}
func (c *ClusterConfig) newClusterBackend(namespace string, backend *netv1.IngressServiceBackend, balance annotations.Balance, services map[string]*corev1.Service, endpoints map[string]*corev1.Endpoints) cluster_table_conf.ClusterBackend {
	subClusters := make(cluster_table_conf.ClusterBackend)
	if backend == nil {
		return subClusters
	}
	weights, ok := balance[backend.Name]
	if !ok {
		serviceName := util.NamespacedName(namespace, backend.Name)
		port := getTargetPort(backend.Port, services[serviceName])
		subClusters[serviceName] = c.newSubClusterBackend(endpoints[serviceName], port)
		return subClusters
	}
	for name := range weights {
		serviceName := util.NamespacedName(namespace, name)
		port := getTargetPort(backend.Port, services[serviceName])
		subClusters[serviceName] = c.newSubClusterBackend(endpoints[serviceName], port)
	}
	return subClusters
}