Skip to content

Commit

Permalink
Revert "Remove old PlayerNext (gravitational#513)" (gravitational#515)
Browse files Browse the repository at this point in the history
This reverts commit 81109fa.
  • Loading branch information
alex-kovoy authored Dec 17, 2021
1 parent 81109fa commit cafe419
Show file tree
Hide file tree
Showing 27 changed files with 64,387 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1082,7 +1082,7 @@ exports[`list of all events 1`] = `
class="c11"
>
<a
href="/web/cluster/im-a-cluster/player/941a4c65-c6cd-11ea-9bef-482ae3513733"
href="/web/cluster/im-a-cluster/session/941a4c65-c6cd-11ea-9bef-482ae3513733"
style="text-decoration: none;"
target="_blank"
title="Open Session Player"
Expand Down
23 changes: 23 additions & 0 deletions web/packages/teleport/src/PlayerNext/BpfLogs/BpfLogs.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
Copyright 2019 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import React from 'react';
import BpfViewer from 'shared/components/BpfViewer';

export default function BpfLogs() {
const ref = React.useRef();
return <BpfViewer ref={ref} events={[]} />;
}
18 changes: 18 additions & 0 deletions web/packages/teleport/src/PlayerNext/BpfLogs/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
Copyright 2019 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import BpfLogs from './BpfLogs';
export default BpfLogs;
49 changes: 49 additions & 0 deletions web/packages/teleport/src/PlayerNext/BpfPlayer/BpfPlayer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
Copyright 2019 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import BpfViewer, { formatEvents } from 'shared/components/BpfViewer';
import useTtyBpfMapper from './useTtyBpfMapper';

export default function BpfLogs({ tty, events, split }) {
const cursor = useTtyBpfMapper(tty, events);
const ref = React.useRef();

React.useEffect(() => {
const { session, editor } = ref.current;
const length = session.getLength();
const doc = session.getDocument();

// clear the content and insert the first line
if (cursor === 0) {
doc.removeFullLines(0, length);
editor.insert(formatEvents([events[0]]).join('\n'));
} else if (cursor > length) {
const sliced = formatEvents(events.slice(length, cursor));
const formatted = `\n${sliced.join('\n')}`;
session.insert({ row: length, column: 0 }, formatted);
} else if (cursor < length) {
doc.removeFullLines(cursor, length);
}

editor.gotoLine(cursor);
}, [cursor]);

React.useEffect(() => {
ref.current.editor.resize();
}, [split]);

return <BpfViewer showGutter={false} ref={ref} events={[]} />;
}
18 changes: 18 additions & 0 deletions web/packages/teleport/src/PlayerNext/BpfPlayer/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
Copyright 2019 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import BpfPlayer from './BpfPlayer';
export default BpfPlayer;
86 changes: 86 additions & 0 deletions web/packages/teleport/src/PlayerNext/BpfPlayer/useTtyBpfMapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
Copyright 2019 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import { throttle } from 'lodash';

export default function useTtyBpfMapper(tty, events) {
// create a map [time][index] for quick lookups
const bpfLookupTable = React.useMemo(() => {
return events.map(i => new Date(i.time));
}, [events]);

// current cursor (index)
const [cursor, setCursor] = React.useState(() => {
return mapTtyToBpfEvent(tty, bpfLookupTable);
});

React.useEffect(() => {
function onChange() {
const index = mapTtyToBpfEvent(tty, bpfLookupTable);
setCursor(index);
}

const throttledOnChange = throttle(onChange, 100);

function cleanup() {
throttledOnChange.cancel();
tty.removeListener('change', throttledOnChange);
}

tty.on('change', throttledOnChange);

return cleanup;
}, [tty, events]);

return cursor;
}

function mapTtyToBpfEvent(tty, bpfLookupTable = []) {
if (bpfLookupTable.length === 0) {
return -1;
}

// return the last event index if player exceeded
// the total number of events
if (tty.currentEventIndex >= tty._eventProvider.events.length) {
return bpfLookupTable.length;
}

const ttyEvent = tty._eventProvider.events[tty.currentEventIndex];
return getEventIndex(ttyEvent.time, bpfLookupTable);
}

// finds event index by datetime using binary search
function getEventIndex(datetime, lookupTable) {
const arr = lookupTable;
var low = 0;
var hi = arr.length - 1;

while (hi - low > 1) {
const mid = Math.floor((low + hi) / 2);
if (arr[mid] < datetime) {
low = mid;
} else {
hi = mid;
}
}

if (datetime - arr[low] <= arr[hi] - datetime) {
return low;
}

return hi;
}
84 changes: 84 additions & 0 deletions web/packages/teleport/src/PlayerNext/Player.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
Copyright 2019 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import React from 'react';
import styled from 'styled-components';
import { Flex } from 'design';
import {
Redirect,
Route,
useParams,
useRouteMatch,
} from 'teleport/components/Router';
import { colors } from 'teleport/Console/colors';
import cfg from 'teleport/config';
import Tabs, { TabItem } from './PlayerTabs';
import SshPlayer from './SshPlayer';
import BpfLogs from './BpfLogs';

export default function SessionAudit() {
const { sid, clusterId } = useParams();
const indexRoute = cfg.getPlayerRoute({ clusterId, sid });
const playerRoute = cfg.getSessionAuditPlayerRoute({ clusterId, sid });
const cmdsRoute = cfg.getSessionAuditCmdsRoute({ clusterId, sid });

const isCmdTabActive = Boolean(useRouteMatch(cfg.routes.sessionAuditCmds));
const isPlayerTabActive = Boolean(
useRouteMatch(cfg.routes.sessionAuditPlayer)
);

return (
<StyledPlayer>
<Tabs>
<TabItem to={playerRoute} title="Player" />
<TabItem to={cmdsRoute} title="Commands" />
</Tabs>
<StyledDocument visible={isPlayerTabActive}>
<SshPlayer sid={sid} clusterId={clusterId} />
</StyledDocument>
<StyledDocument visible={isCmdTabActive}>
<BpfLogs />
</StyledDocument>
<Route exact path={indexRoute}>
<Redirect to={playerRoute} />
</Route>
</StyledPlayer>
);
}

const StyledPlayer = styled.div`
display: flex;
height: 100%;
width: 100%;
position: absolute;
flex-direction: column;
`;

function StyledDocument({ children, visible }) {
return (
<Flex
bg={colors.bgTerminal}
flex="1"
style={{
overflow: 'auto',
display: visible ? 'flex' : 'none',
position: 'relative',
}}
>
{children}
</Flex>
);
}
39 changes: 39 additions & 0 deletions web/packages/teleport/src/PlayerNext/Player.story.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
Copyright 2019 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import React from 'react';
import { Router, Route } from 'teleport/components/Router';
import PlayerComponent from './Player';
import { createMemoryHistory } from 'history';

export default {
title: 'Teleport/PlayerNext',
};

export const Player = () => {
const history = createMemoryHistory({
initialEntries: ['/web/cluster/localhost/session/123'],
initialIndex: 0,
});

return (
<Router history={history}>
<Route path="/web/cluster/:clusterId/session/:sid">
<PlayerComponent />
</Route>
</Router>
);
};
Loading

0 comments on commit cafe419

Please sign in to comment.