blob: 3f112a3416624c11992218e80ebc2849d0a58dfe [file] [log] [blame]
package portforwardutil
import (
"context"
"fmt"
"net/http"
"net/url"
"os"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/portforward"
"k8s.io/client-go/transport/spdy"
)
func NewForService(config *rest.Config, service *v1.Service, port int) (*portforward.PortForwarder, error) {
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
ep, err := clientset.CoreV1().Endpoints(service.Namespace).Get(
context.TODO(),
service.Name,
metav1.GetOptions{},
)
if err != nil {
return nil, err
}
if len(ep.Subsets) == 0 {
return nil, fmt.Errorf("no subsets found")
}
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: ep.Subsets[0].Addresses[0].TargetRef.Name,
Namespace: service.Namespace,
},
}
return NewForPod(config, pod, port)
}
func NewForPod(config *rest.Config, pod *v1.Pod, port int) (*portforward.PortForwarder, error) {
streams := genericclioptions.IOStreams{
In: os.Stdin,
Out: os.Stdout,
ErrOut: os.Stderr,
}
parsedUrl, err := url.Parse(config.Host)
if err != nil {
return nil, err
}
parsedUrl.Path = fmt.Sprintf(
"/api/v1/namespaces/%s/pods/%s/portforward",
pod.Namespace, pod.Name,
)
transport, upgrader, err := spdy.RoundTripperFor(config)
if err != nil {
return nil, err
}
dialer := spdy.NewDialer(
upgrader,
&http.Client{Transport: transport},
http.MethodPost,
parsedUrl,
)
return portforward.New(
dialer,
[]string{fmt.Sprintf("%d:%d", 3306, port)},
make(chan struct{}),
make(chan struct{}),
streams.Out,
streams.ErrOut,
)
}