-
Notifications
You must be signed in to change notification settings - Fork 476
/
port_forwarder.go
92 lines (76 loc) · 2 KB
/
port_forwarder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package httputil
import (
"io"
"net/http"
"os"
"strconv"
"strings"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/portforward"
"k8s.io/client-go/transport/spdy"
"github.com/kiali/kiali/log"
)
type PortForwarder interface {
Start() error
Stop()
}
type forwarder struct {
forwarder *portforward.PortForwarder
ReadyCh chan struct{}
StopCh chan struct{}
localPort int
}
func (f forwarder) Start() error {
// It starts the port-forward
errCh := make(chan error, 1)
go func() {
errCh <- f.forwarder.ForwardPorts()
}()
// Waiting until the ReadyChan has a value
select {
case err := <-errCh:
log.Error("Failing starting the port forwarding")
return err
case <-f.ReadyCh:
// Ready to forward requests
return nil
}
}
func (f forwarder) Stop() {
// Closing the StopCh channel is closing the forwarding
close(f.StopCh)
Pool.FreePort(f.localPort)
}
func NewPortForwarder(client *rest.Interface, clientConfig *rest.Config, namespace, pod, address, portMap string, writer io.Writer) (*PortForwarder, error) {
stopCh := make(chan struct{})
readyCh := make(chan struct{})
forwarderUrl := (*client).Post().
Namespace(namespace).
Resource("pods").
Name(pod).
SubResource("portforward").URL()
transport, upgrader, err := spdy.RoundTripperFor(clientConfig)
if err != nil {
log.Errorf("Error creating a RoundTripper: %v", err)
return nil, err
}
dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, http.MethodPost, forwarderUrl)
fwer, err := portforward.NewOnAddresses(dialer, []string{address}, []string{portMap},
stopCh, readyCh, writer, os.Stderr)
if err != nil {
log.Errorf("Error creating the port-forwarder: %v", err)
return nil, err
}
localPort, err := strconv.Atoi(strings.Split(portMap, ":")[0])
if err != nil {
log.Errorf("wrong port mapping between local port and destination port: %v", err)
return nil, err
}
f := PortForwarder(forwarder{
forwarder: fwer,
ReadyCh: readyCh,
StopCh: stopCh,
localPort: localPort,
})
return &f, nil
}