Skip to content

Commit

Permalink
Pod attach/exec proto (#1939)
Browse files Browse the repository at this point in the history
* Added go vendor dependencies for shell module

- github.com/gorilla/websocket
- gopkg.in/igm/sockjs-go.v2/sockjs
- k8s.io/kubernetes/pkg/client/unversioned/remotecommand

* Added shell module
  • Loading branch information
lenartj authored and floreks committed Jun 16, 2017
1 parent f534482 commit d8f28e8
Show file tree
Hide file tree
Showing 127 changed files with 11,834 additions and 7 deletions.
4 changes: 3 additions & 1 deletion bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
"ng-jsoneditor": "angular-tools/ng-jsoneditor#~1.0.0",
"angularUtils-pagination": "angular-utils-pagination#~0.11.1",
"easyfont-roboto-mono": "easyfont/roboto-mono#fa7971ea56f68bfdb2771f9cb560c99aca0164c1",
"angular-clipboard": "^1.5.0"
"angular-clipboard": "^1.5.0",
"hterm": "~1.0.0",
"sockjs-client": "^1.1.4"
},
"overrides": {
"material-design-icons": {
Expand Down
3 changes: 3 additions & 0 deletions build/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ function compileES6(translation) {
path.join(conf.paths.externs, 'dataselect.js'),
path.join(conf.paths.externs, 'dirPagination.js'),
path.join(conf.paths.externs, 'searchapi.js'),
path.join(conf.paths.externs, 'shell.js'),
path.join(conf.paths.externs, 'hterm.js'),
path.join(conf.paths.externs, 'sockjs.js'),
];

let closureCompilerConfig = {
Expand Down
13 changes: 7 additions & 6 deletions build/serve.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ import browserSync from 'browser-sync';
import browserSyncSpa from 'browser-sync-spa';
import child from 'child_process';
import gulp from 'gulp';
import proxyMiddleware from 'http-proxy-middleware';
import path from 'path';
import proxyMiddleware from 'proxy-middleware';
import url from 'url';
import conf from './conf';

/**
Expand Down Expand Up @@ -77,17 +76,19 @@ function browserSyncInit(baseDir, includeBowerComponents) {
}));

let apiRoute = '/api';
let proxyMiddlewareOptions =
url.parse(`http://localhost:${conf.backend.devServerPort}${apiRoute}`);
proxyMiddlewareOptions.route = apiRoute;
let proxyMiddlewareOptions = {
target: `http://localhost:${conf.backend.devServerPort}`,
// proxy websockets
ws: true,
};

let config = {
browser: [], // Needed so that the browser does not auto-launch.
directory: false, // Disable directory listings.
// TODO(bryk): Add proxy to the backend here.
server: {
baseDir: baseDir,
middleware: proxyMiddleware(proxyMiddlewareOptions),
middleware: proxyMiddleware(apiRoute, proxyMiddlewareOptions),
},
port: conf.frontend.serverPort,
startPath: '/',
Expand Down
1 change: 1 addition & 0 deletions src/app/backend/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ func main() {
http.Handle("/api/", apiHandler)
// TODO(maciaszczykm): Move to /appConfig.json as it was discussed in #640.
http.Handle("/api/appConfig.json", handler.AppHandler(handler.ConfigHandler))
http.Handle("/api/sockjs/", handler.CreateAttachHandler("/api/sockjs"))
http.Handle("/metrics", prometheus.Handler())

// Listen for http and https
Expand Down
40 changes: 40 additions & 0 deletions src/app/backend/handler/apihandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import (
"golang.org/x/net/xsrftoken"
errorsK8s "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
)

const (
Expand All @@ -76,6 +77,12 @@ type APIHandler struct {
manager client.ClientManager
}

// TerminalResponse is sent by handleExecShell. The Id is a random session id that binds the original REST request and the SockJS connection.
// Any client in possession of this Id can hijack the terminal session.
type TerminalResponse struct {
Id string `json:"id"`
}

// CreateHTTPAPIHandler creates a new HTTP handler that handles all requests to the API of the backend.
func CreateHTTPAPIHandler(heapsterClient heapster.HeapsterClient, manager client.ClientManager) (
http.Handler, error) {
Expand Down Expand Up @@ -238,6 +245,10 @@ func CreateHTTPAPIHandler(heapsterClient heapster.HeapsterClient, manager client
apiV1Ws.GET("/pod/{namespace}/{pod}/event").
To(apiHandler.handleGetPodEvents).
Writes(common.EventList{}))
apiV1Ws.Route(
apiV1Ws.GET("/pod/{namespace}/{pod}/shell/{container}").
To(apiHandler.handleExecShell).
Writes(TerminalResponse{}))

apiV1Ws.Route(
apiV1Ws.GET("/deployment").
Expand Down Expand Up @@ -1148,6 +1159,35 @@ func (apiHandler *APIHandler) handleGetPodEvents(request *restful.Request, respo
response.WriteHeaderAndEntity(http.StatusOK, result)
}

// Handles execute shell API call
func (apiHandler *APIHandler) handleExecShell(request *restful.Request, response *restful.Response) {
sessionId, err := genTerminalSessionId()
if err != nil {
handleInternalError(response, err)
return
}

k8sClient, err := apiHandler.manager.Client(request)
if err != nil {
handleInternalError(response, err)
return
}

cfg, err := apiHandler.manager.Config(request)
if err != nil {
handleInternalError(response, err)
return
}

terminalSessions[sessionId] = TerminalSession{
id: sessionId,
bound: make(chan error),
sizeChan: make(chan remotecommand.TerminalSize),
}
go WaitForTerminal(k8sClient, cfg, request, sessionId)
response.WriteHeaderAndEntity(http.StatusOK, TerminalResponse{Id: sessionId})
}

func (apiHandler *APIHandler) handleGetDeployments(request *restful.Request, response *restful.Response) {
k8sClient, err := apiHandler.manager.Client(request)
if err != nil {
Expand Down
Loading

0 comments on commit d8f28e8

Please sign in to comment.