func ServiceKey(hostname string, servicePorts PortList, labelsList LabelsCollection) string {
	var buffer bytes.Buffer
	buffer.WriteString(hostname)
	np := len(servicePorts)
	nt := len(labelsList)
	if nt == 1 && labelsList[0] == nil {
		nt = 0
	}
	if np == 0 && nt == 0 {
		return buffer.String()
	} else if np == 1 && nt == 0 && servicePorts[0].Name == "" {
		return buffer.String()
	} else {
		buffer.WriteString("|")
	}
	if np > 0 {
		ports := make([]string, np)
		for i := 0; i < np; i++ {
			ports[i] = servicePorts[i].Name
		}
		sort.Strings(ports)
		for i := 0; i < np; i++ {
			if i > 0 {
				buffer.WriteString(",")
			}
			buffer.WriteString(ports[i])
		}
	}
	if nt > 0 {
		buffer.WriteString("|")
		labels := make([]string, nt)
		for i := 0; i < nt; i++ {
			labels[i] = labelsList[i].String()
		}
		sort.Strings(labels)
		for i := 0; i < nt; i++ {
			if i > 0 {
				buffer.WriteString(";")
			}
			buffer.WriteString(labels[i])
		}
	}
	return buffer.String()
}
ServiceKey generates a service key for a collection of ports and labels
package model
import (
	"bytes"
	"fmt"
	"sort"
	"strings"
)
type Service struct {
	Hostname string `json:"hostname"`
	Address string `json:"address,omitempty"`
	Ports PortList `json:"ports,omitempty"`
	ExternalName string `json:"external"`
	ServiceAccounts []string `json:"serviceaccounts,omitempty"`
	LoadBalancingDisabled bool `json:"-"`
}
type Port struct {
	Name string `json:"name,omitempty"`
	Port int `json:"port"`
	Protocol Protocol `json:"protocol,omitempty"`
	AuthenticationPolicy AuthenticationPolicy `json:"authentication_policy,omitempty"`
}
type PortList []*Port
type Protocol string
const (
	ProtocolGRPC Protocol = "GRPC"
	ProtocolHTTPS Protocol = "HTTPS"
	ProtocolHTTP2 Protocol = "HTTP2"
	ProtocolHTTP Protocol = "HTTP"
	ProtocolTCP Protocol = "TCP"
	ProtocolUDP Protocol = "UDP"
	ProtocolMongo Protocol = "Mongo"
	ProtocolRedis Protocol = "Redis"
)
type AuthenticationPolicy string
const (
	AuthenticationEnable AuthenticationPolicy = "enable"
	AuthenticationDisable AuthenticationPolicy = "disable"
	AuthenticationDefault AuthenticationPolicy = ""
)
func (p Protocol) IsHTTP() bool {
	switch p {
	case ProtocolHTTP, ProtocolHTTP2, ProtocolGRPC:
		return true
	default:
		return false
	}
}
type NetworkEndpoint struct {
	Address string `json:"ip_address,omitempty"`
	Port int `json:"port"`
	ServicePort *Port `json:"service_port"`
}
type Labels map[string]string
type LabelsCollection []Labels
type ServiceInstance struct {
	Endpoint         NetworkEndpoint `json:"endpoint,omitempty"`
	Service          *Service        `json:"service,omitempty"`
	Labels           Labels          `json:"labels,omitempty"`
	AvailabilityZone string          `json:"az,omitempty"`
	ServiceAccount   string          `json:"serviceaccount,omitempty"`
}
type ServiceDiscovery interface {
	Services() ([]*Service, error)
	GetService(hostname string) (*Service, error)
	Instances(hostname string, ports []string, labels LabelsCollection) ([]*ServiceInstance, error)
	HostInstances(addrs map[string]bool) ([]*ServiceInstance, error)
	ManagementPorts(addr string) PortList
}
type ServiceAccounts interface {
	GetIstioServiceAccounts(hostname string, ports []string) []string
}
func (t Labels) SubsetOf(that Labels) bool {
	for k, v := range t {
		if that[k] != v {
			return false
		}
	}
	return true
}
func (t Labels) Equals(that Labels) bool {
	if t == nil {
		return that == nil
	}
	if that == nil {
		return t == nil
	}
	return t.SubsetOf(that) && that.SubsetOf(t)
}
func (labels LabelsCollection) HasSubsetOf(that Labels) bool {
	if len(labels) == 0 {
		return true
	}
	for _, tag := range labels {
		if tag.SubsetOf(that) {
			return true
		}
	}
	return false
}
func (ports PortList) GetNames() []string {
	names := make([]string, 0, len(ports))
	for _, port := range ports {
		names = append(names, port.Name)
	}
	return names
}
func (ports PortList) Get(name string) (*Port, bool) {
	for _, port := range ports {
		if port.Name == name {
			return port, true
		}
	}
	return nil, false
}
func (ports PortList) GetByPort(num int) (*Port, bool) {
	for _, port := range ports {
		if port.Port == num {
			return port, true
		}
	}
	return nil, false
}
func (s *Service) External() bool {
	return s.ExternalName != ""
}
func (s *Service) Key(port *Port, tag Labels) string {
	return ServiceKey(s.Hostname, PortList{port}, LabelsCollection{tag})
}