func ResolveServicePorts(log logrus.FieldLogger, s *corev1.Service) ([]ResolvedServicePort, error) {  
	store := kevents.GlobalCache.Core().V1().Endpoints().Informer().GetStore()
	hasNamedPorts := false
	for _, p := range s.Spec.Ports {
		if p.TargetPort.Type == intstr.String {
			hasNamedPorts = true
			break
		}
	}
	if !hasNamedPorts {
		servicePorts := make([]ResolvedServicePort, len(s.Spec.Ports))
		for i, sp := range s.Spec.Ports {
			servicePorts[i] = ResolvedServicePort{
				sp,
				"",
				uint(sp.Port),
			}
		}
		return servicePorts, nil
	}
	obj, _, err := store.GetByKey(s.Namespace + "/" + s.Name)
	e, ok := obj.(*corev1.Endpoints)
	if !ok || len(e.Subsets) == 0 || err != nil {
		return ResolveServicePortsFromControllers(log, s)
	}
	servicePorts := make([]ResolvedServicePort, len(s.Spec.Ports))
	for i, p := range s.Spec.Ports {
		original := ""
		if p.TargetPort.Type == intstr.String {
			if len(e.Subsets) == 0 {
				continue
			}
			for _, np := range e.Subsets[0].Ports {
				if np.Name == p.Name || np.Name == p.TargetPort.String() {
					original = p.TargetPort.String()
					p.TargetPort = intstr.FromInt(int(np.Port))
					break
				}
			}
		}
		servicePorts[i] = ResolvedServicePort{
			p,
			original,
			uint(p.TargetPort.IntValue()),
		}
	}
	return servicePorts, nil
}
ResolveServicePorts converts named ports into their true
format. TargetPort's that have are named become their integer equivalents
package kube
import (
	"context"
	"fmt"
	"io/ioutil"
	"net/http"
	"github.com/getoutreach/localizer/internal/kevents"
	"github.com/getoutreach/localizer/internal/reflectconversions"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/conversion"
	"k8s.io/apimachinery/pkg/util/intstr"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/transport/spdy"
	_ "k8s.io/client-go/plugin/pkg/client/auth"
	"k8s.io/client-go/tools/clientcmd"
	"k8s.io/client-go/tools/portforward"
	"k8s.io/client-go/rest"
)
func GetKubeClient(contextName string) (*rest.Config, kubernetes.Interface, error) {
	config, err := rest.InClusterConfig()
	if err != nil {
		lr := clientcmd.NewDefaultClientConfigLoadingRules()
		overrides := &clientcmd.ConfigOverrides{}
		if contextName != "" {
			overrides.CurrentContext = contextName
		}
		config, err = clientcmd.NewNonInteractiveDeferredLoadingClientConfig(lr, overrides).ClientConfig()
		if err != nil {
			return nil, nil, errors.Wrap(err, "failed to get kubernetes client config")
		}
	}
	client, err := kubernetes.NewForConfig(config)
	if err != nil {
		return nil, nil, errors.Wrap(err, "failed to create kubernetes client")
	}
	return config, client, nil
}
func CreatePortForward(ctx context.Context, r rest.Interface, rc *rest.Config,
	p *corev1.Pod, ip string, ports []string) (*portforward.PortForwarder, error) {
	req := r.Post().
		Resource("pods").
		Namespace(p.Namespace).
		Name(p.Name).
		SubResource("portforward")
	transport, upgrader, err := spdy.RoundTripperFor(rc)
	if err != nil {
		return nil, err
	}
	dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, "POST", req.URL())
	return portforward.NewOnAddresses(dialer, []string{ip}, ports, ctx.Done(), nil, ioutil.Discard, ioutil.Discard)
}
type ResolvedServicePort struct {
	corev1.ServicePort
	OriginalTargetPort string
	MappedPort uint
}