func (s *Service) TargetPort() *uint16 {
	for _, endpoint := range s.endpoints {
		port := endpoint.Port()
		return &port
	}
	return nil
}
TargetPort resolves target port using endpoint information
package v1alpha1
import (
	"fmt"
	"net"
	"reflect"
	"strings"
	"syscall"
	"github.com/Demonware/balanced/pkg/util"
	"github.com/golang/glog"
	deadlock "github.com/sasha-s/go-deadlock"
	api "k8s.io/api/core/v1"
)
type EndpointOnChangeHandler func(prevE *Endpoint, updatedE *Endpoint)
var ProtoNameToNumberMap = map[api.Protocol]uint16{
	api.ProtocolTCP: syscall.IPPROTO_TCP,
	api.ProtocolUDP: syscall.IPPROTO_UDP,
}
type Service struct {
	ip          *net.IP
	port        api.ServicePort
	protocol    api.Protocol
	kubeService *api.Service
	endpoints map[string]*Endpoint
	m         deadlock.Mutex
}
type ServiceOption func(*Service) error
type ServiceUpdateRecord struct {
	Added   []*Endpoint
	Updated []*Endpoint
	Removed []*Endpoint
	Ignored []*Endpoint
}
func getLoadBalancerIP(kubeService *api.Service) (ip *net.IP) {
	for _, ingressObj := range kubeService.Status.LoadBalancer.Ingress {
		if ingressObj.IP != "" {
			addr := net.ParseIP(ingressObj.IP)
			ip = &addr
			return
		}
	}
	return
}
func ConvertKubeAPIV1ServiceToServices(kubeService *api.Service, opts ...ServiceOption) ([]*Service, error) {
	var svcs []*Service
	for _, portSpec := range kubeService.Spec.Ports {
		var svc *Service
		svc, err := NewService(kubeService, portSpec, opts...)
		if err != nil {
			return nil, err
		}
		svcs = append(svcs, svc)
	}
	return svcs, nil
}
func NewService(kubeService *api.Service, portSpec api.ServicePort, opts ...ServiceOption) (*Service, error) {
	s := &Service{
		ip:          getLoadBalancerIP(kubeService),
		port:        portSpec,
		protocol:    portSpec.Protocol,
		kubeService: kubeService,
		endpoints:   make(map[string]*Endpoint),
	}
	for _, opt := range opts {
		if err := opt(s); err != nil {
			return nil, err
		}
	}
	return s, nil
}