github.com/secure-build/gitlab-runner@v12.5.0+incompatible/executors/kubernetes/terminal.go (about)

     1  package kubernetes
     2  
     3  import (
     4  	"io/ioutil"
     5  	"net/http"
     6  	"net/url"
     7  
     8  	terminal "gitlab.com/gitlab-org/gitlab-terminal"
     9  	api "k8s.io/api/core/v1"
    10  	"k8s.io/client-go/kubernetes/scheme"
    11  	restclient "k8s.io/client-go/rest"
    12  
    13  	"gitlab.com/gitlab-org/gitlab-runner/session/proxy"
    14  	terminalsession "gitlab.com/gitlab-org/gitlab-runner/session/terminal"
    15  )
    16  
    17  func (s *executor) Connect() (terminalsession.Conn, error) {
    18  	settings, err := s.getTerminalSettings()
    19  	if err != nil {
    20  		return nil, err
    21  	}
    22  
    23  	return terminalConn{settings: settings}, nil
    24  }
    25  
    26  type terminalConn struct {
    27  	settings *terminal.TerminalSettings
    28  }
    29  
    30  func (t terminalConn) Start(w http.ResponseWriter, r *http.Request, timeoutCh, disconnectCh chan error) {
    31  	wsProxy := terminal.NewWebSocketProxy(1) // one stopper: terminal exit handler
    32  
    33  	terminalsession.ProxyTerminal(
    34  		timeoutCh,
    35  		disconnectCh,
    36  		wsProxy.StopCh,
    37  		func() {
    38  			terminal.ProxyWebSocket(w, r, t.settings, wsProxy)
    39  		},
    40  	)
    41  }
    42  
    43  func (t terminalConn) Close() error {
    44  	return nil
    45  }
    46  
    47  func (s *executor) getTerminalSettings() (*terminal.TerminalSettings, error) {
    48  	config, err := getKubeClientConfig(s.Config.Kubernetes, s.configurationOverwrites)
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  
    53  	wsURL, err := s.getTerminalWebSocketURL(config)
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  
    58  	caCert := ""
    59  	if len(config.CAFile) > 0 {
    60  		buf, err := ioutil.ReadFile(config.CAFile)
    61  		if err != nil {
    62  			return nil, err
    63  		}
    64  		caCert = string(buf)
    65  	}
    66  
    67  	term := &terminal.TerminalSettings{
    68  		Subprotocols:   []string{"channel.k8s.io"},
    69  		Url:            wsURL.String(),
    70  		Header:         http.Header{"Authorization": []string{"Bearer " + config.BearerToken}},
    71  		CAPem:          caCert,
    72  		MaxSessionTime: 0,
    73  	}
    74  
    75  	return term, nil
    76  }
    77  
    78  func (s *executor) getTerminalWebSocketURL(config *restclient.Config) (*url.URL, error) {
    79  	wsURL := s.kubeClient.CoreV1().RESTClient().Post().
    80  		Namespace(s.pod.Namespace).
    81  		Resource("pods").
    82  		Name(s.pod.Name).
    83  		SubResource("exec").
    84  		VersionedParams(&api.PodExecOptions{
    85  			Stdin:     true,
    86  			Stdout:    true,
    87  			Stderr:    true,
    88  			TTY:       true,
    89  			Container: "build",
    90  			Command:   []string{"sh", "-c", "bash || sh"},
    91  		}, scheme.ParameterCodec).URL()
    92  
    93  	wsURL.Scheme = proxy.WebsocketProtocolFor(wsURL.Scheme)
    94  	return wsURL, nil
    95  }