/
terminal.go
95 lines (79 loc) · 2.21 KB
/
terminal.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
package kubernetes
import (
"io/ioutil"
"net/http"
"net/url"
terminal "gitlab.com/gitlab-org/gitlab-terminal"
api "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes/scheme"
restclient "k8s.io/client-go/rest"
"gitlab.com/gitlab-org/gitlab-runner/session/proxy"
terminalsession "gitlab.com/gitlab-org/gitlab-runner/session/terminal"
)
func (s *executor) Connect() (terminalsession.Conn, error) {
settings, err := s.getTerminalSettings()
if err != nil {
return nil, err
}
return terminalConn{settings: settings}, nil
}
type terminalConn struct {
settings *terminal.TerminalSettings
}
func (t terminalConn) Start(w http.ResponseWriter, r *http.Request, timeoutCh, disconnectCh chan error) {
wsProxy := terminal.NewWebSocketProxy(1) // one stopper: terminal exit handler
terminalsession.ProxyTerminal(
timeoutCh,
disconnectCh,
wsProxy.StopCh,
func() {
terminal.ProxyWebSocket(w, r, t.settings, wsProxy)
},
)
}
func (t terminalConn) Close() error {
return nil
}
func (s *executor) getTerminalSettings() (*terminal.TerminalSettings, error) {
config, err := getKubeClientConfig(s.Config.Kubernetes, s.configurationOverwrites)
if err != nil {
return nil, err
}
wsURL, err := s.getTerminalWebSocketURL(config)
if err != nil {
return nil, err
}
caCert := ""
if len(config.CAFile) > 0 {
buf, err := ioutil.ReadFile(config.CAFile)
if err != nil {
return nil, err
}
caCert = string(buf)
}
term := &terminal.TerminalSettings{
Subprotocols: []string{"channel.k8s.io"},
Url: wsURL.String(),
Header: http.Header{"Authorization": []string{"Bearer " + config.BearerToken}},
CAPem: caCert,
MaxSessionTime: 0,
}
return term, nil
}
func (s *executor) getTerminalWebSocketURL(config *restclient.Config) (*url.URL, error) {
wsURL := s.kubeClient.CoreV1().RESTClient().Post().
Namespace(s.pod.Namespace).
Resource("pods").
Name(s.pod.Name).
SubResource("exec").
VersionedParams(&api.PodExecOptions{
Stdin: true,
Stdout: true,
Stderr: true,
TTY: true,
Container: "build",
Command: []string{"sh", "-c", "bash || sh"},
}, scheme.ParameterCodec).URL()
wsURL.Scheme = proxy.WebsocketProtocolFor(wsURL.Scheme)
return wsURL, nil
}