-
Notifications
You must be signed in to change notification settings - Fork 13
/
kubetunnel.go
139 lines (105 loc) · 3.37 KB
/
kubetunnel.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package pkg
import (
"fmt"
log "github.com/sirupsen/logrus"
"github.com/txn2/kubefwd/pkg/fwdport"
"github.com/txn2/kubefwd/pkg/utils"
"github.com/we-dcode/kube-tunnel/pkg/clients/helm"
"github.com/we-dcode/kube-tunnel/pkg/clients/kube"
"github.com/we-dcode/kube-tunnel/pkg/clients/kube/servicecontext"
"github.com/we-dcode/kube-tunnel/pkg/constants"
"github.com/we-dcode/kube-tunnel/pkg/frp/frpc"
frpmodels "github.com/we-dcode/kube-tunnel/pkg/frp/models"
"github.com/we-dcode/kube-tunnel/pkg/kubefwd"
"github.com/we-dcode/kube-tunnel/pkg/models"
"os"
)
type KubeTunnel struct {
kubeClient *kube.Kube
helmClient *helm.Helm
}
type KubeTunnelConf struct {
ServiceName string
KubeTunnelPortMap map[string]string
LocalIP string
}
func MustNewKubeTunnel(kubeConfig string, namespace string, privileged bool) *KubeTunnel {
if len(kubeConfig) > 0 {
_ = os.Setenv("KUBECONFIG", kubeConfig) // Workaround for internal client created by kubefwd
}
kubeClient := kube.MustNew(kubeConfig, namespace)
err := kubeClient.ConnectivityCheck()
if err != nil {
log.Panicf(err.Error())
}
err = kubeClient.RBACCheck()
if err != nil {
log.Panicf(err.Error())
}
if privileged {
err = CheckRootPermissions()
if err != nil {
log.Panicf(err.Error())
}
}
helmClient := helm.MustNew(kubeClient)
return &KubeTunnel{
kubeClient: kubeClient,
helmClient: helmClient,
}
}
func (ct *KubeTunnel) Install(operatorVersion string) {
err := ct.helmClient.InstallKubeTunnelOperator(operatorVersion)
if err != nil {
log.Panic(err.Error())
}
}
func (ct *KubeTunnel) CreateTunnel(tunnelConf KubeTunnelConf) {
svcCtx, err := ct.kubeClient.GetServiceContext(tunnelConf.ServiceName)
if err != nil {
log.Panic(err.Error())
}
labels, err := ct.kubeClient.GetPodLabelsByLabelSelector(ct.kubeClient.Namespace, svcCtx.LabelSelector)
if err != nil {
log.Panic(err.Error())
}
kubeTunnelResourceSpec := servicecontext.ToKubeTunnelResourceSpec(svcCtx, labels)
if err = ct.kubeClient.CreateKubeTunnelResource(kubeTunnelResourceSpec); err != nil {
log.Panicf("fail creating kubetunnel CRD, internal error: %s", err.Error())
}
kubefwdSyncChannel := make(chan error)
var hostFile *fwdport.HostFileWithLock
go func(ktrs *models.KubeTunnelResourceSpec) {
hostFile = kubefwd.Execute(ct.kubeClient, ktrs, kubefwdSyncChannel)
}(&kubeTunnelResourceSpec)
err = <-kubefwdSyncChannel
if err != nil {
log.Panicf("fail executing kubefwd: %s", err.Error())
}
log.Info("executing frpc")
common := frpmodels.Common{
ServerAddress: fmt.Sprintf("%s-%s", constants.KubetunnelSlug, kubeTunnelResourceSpec.ServiceName),
ServerPort: constants.FRPServerPort,
}
servicePortsPairs := servicecontext.ToFRPClientPairs(tunnelConf.LocalIP, tunnelConf.KubeTunnelPortMap, svcCtx)
frpcManager := frpc.NewManager(common, servicePortsPairs, hostFile)
frpcManager.RunFRPc()
}
func CheckRootPermissions() error {
hasRoot, err := utils.CheckRoot()
if !hasRoot {
log.Errorf(`
This program requires superuser privileges to run. These
privileges are required to add IP address aliases to your
loopback interface. Superuser privileges are also needed
to listen on low port numbers for these IP addresses.
Try:
- sudo -E kubetunnel (Unix)
- Running a shell with administrator rights (Windows)
`)
if err != nil {
return fmt.Errorf("root check failure: %s", err.Error())
}
}
return nil
}