mirror of
https://github.com/argoproj/argo-cd.git
synced 2026-02-20 01:28:45 +01:00
* feat: add support for default container in logs/exec Signed-off-by: Edward Grönroos <edward@gronroos.se> * chore: resolve linting issues Signed-off-by: Edward Grönroos <edward@gronroos.se>
This commit is contained in:
@@ -25,11 +25,12 @@ export interface PodLogsProps {
|
||||
timestamp?: string;
|
||||
setPage: (pageData: {number: number; untilTimes: string[]}) => void;
|
||||
containerGroups?: any[];
|
||||
onClickContainer?: (group: any, i: number) => any;
|
||||
onClickContainer?: (group: any, i: number, tab: string) => any;
|
||||
}
|
||||
|
||||
export const PodsLogsViewer = (props: PodLogsProps & {fullscreen?: boolean}) => {
|
||||
if (!props.containerName || props.containerName === '') {
|
||||
const {containerName, onClickContainer} = props;
|
||||
if (!containerName || containerName === '') {
|
||||
return <div>Pod does not have container with name {props.containerName}</div>;
|
||||
}
|
||||
|
||||
@@ -55,7 +56,7 @@ export const PodsLogsViewer = (props: PodLogsProps & {fullscreen?: boolean}) =>
|
||||
group.containers.forEach((container: any, index: number) => {
|
||||
const title = (
|
||||
<div className='d-inline-block'>
|
||||
<i className={`fa fa-angle-right ${container.name === props.containerName ? '' : 'invisible'}`} />
|
||||
{container.name === containerName && <i className='fa fa-angle-right' />}
|
||||
<span title={container.name} className='container-item'>
|
||||
{container.name.toUpperCase()}
|
||||
</span>
|
||||
@@ -63,7 +64,7 @@ export const PodsLogsViewer = (props: PodLogsProps & {fullscreen?: boolean}) =>
|
||||
);
|
||||
containerItems.push({
|
||||
title,
|
||||
action: () => (container.name === props.containerName ? {} : props.onClickContainer(group, index))
|
||||
action: () => (container.name === containerName ? {} : onClickContainer(group, index, 'logs'))
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,8 +4,7 @@ import * as models from '../../../shared/models';
|
||||
import * as React from 'react';
|
||||
import './pod-terminal-viewer.scss';
|
||||
import 'xterm/css/xterm.css';
|
||||
import * as AppUtils from '../utils';
|
||||
import {useCallback, useEffect, useState} from 'react';
|
||||
import {useCallback, useEffect} from 'react';
|
||||
import {debounceTime, takeUntil} from 'rxjs/operators';
|
||||
import {fromEvent, ReplaySubject, Subject} from 'rxjs';
|
||||
import {Context} from '../../../shared/context';
|
||||
@@ -15,6 +14,8 @@ export interface PodTerminalViewerProps {
|
||||
projectName: string;
|
||||
selectedNode: models.ResourceNode;
|
||||
podState: models.State;
|
||||
containerName: string;
|
||||
onClickContainer?: (group: any, i: number, tab: string) => any;
|
||||
}
|
||||
export interface ShellFrame {
|
||||
operation: string;
|
||||
@@ -23,14 +24,13 @@ export interface ShellFrame {
|
||||
cols?: number;
|
||||
}
|
||||
|
||||
export const PodTerminalViewer: React.FC<PodTerminalViewerProps> = ({selectedNode, applicationName, projectName, podState}) => {
|
||||
export const PodTerminalViewer: React.FC<PodTerminalViewerProps> = ({selectedNode, applicationName, projectName, podState, containerName, onClickContainer}) => {
|
||||
const terminalRef = React.useRef(null);
|
||||
const appContext = React.useContext(Context); // used to show toast
|
||||
const fitAddon = new FitAddon();
|
||||
let terminal: Terminal;
|
||||
let webSocket: WebSocket;
|
||||
const keyEvent = new ReplaySubject<KeyboardEvent>(2);
|
||||
const [activeContainer, setActiveContainer] = useState(0);
|
||||
let connSubject = new ReplaySubject<ShellFrame>(100);
|
||||
let incommingMessage = new Subject<ShellFrame>();
|
||||
const unsubscribe = new Subject<void>();
|
||||
@@ -143,10 +143,9 @@ export const PodTerminalViewer: React.FC<PodTerminalViewerProps> = ({selectedNod
|
||||
const {name = '', namespace = ''} = selectedNode || {};
|
||||
const url = `${location.host}${appContext.baseHref}`.replace(/\/$/, '');
|
||||
webSocket = new WebSocket(
|
||||
`${location.protocol === 'https:' ? 'wss' : 'ws'}://${url}/terminal?pod=${name}&container=${AppUtils.getContainerName(
|
||||
podState,
|
||||
activeContainer
|
||||
)}&appName=${applicationName}&projectName=${projectName}&namespace=${namespace}`
|
||||
`${
|
||||
location.protocol === 'https:' ? 'wss' : 'ws'
|
||||
}://${url}/terminal?pod=${name}&container=${containerName}&appName=${applicationName}&projectName=${projectName}&namespace=${namespace}`
|
||||
);
|
||||
webSocket.onopen = onConnectionOpen;
|
||||
webSocket.onclose = onConnectionClose;
|
||||
@@ -171,7 +170,7 @@ export const PodTerminalViewer: React.FC<PodTerminalViewerProps> = ({selectedNod
|
||||
// Save a reference to the node
|
||||
terminalRef.current = node;
|
||||
},
|
||||
[activeContainer]
|
||||
[containerName]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -202,7 +201,7 @@ export const PodTerminalViewer: React.FC<PodTerminalViewerProps> = ({selectedNod
|
||||
|
||||
incommingMessage.complete();
|
||||
};
|
||||
}, [activeContainer]);
|
||||
}, [containerName]);
|
||||
|
||||
const containerGroups = [
|
||||
{
|
||||
@@ -228,12 +227,12 @@ export const PodTerminalViewer: React.FC<PodTerminalViewerProps> = ({selectedNod
|
||||
className='application-details__container'
|
||||
key={container.name}
|
||||
onClick={() => {
|
||||
if (group.offset + i !== activeContainer) {
|
||||
if (container.name !== containerName) {
|
||||
disconnect();
|
||||
setActiveContainer(group.offset + i);
|
||||
onClickContainer(group, i, 'exec');
|
||||
}
|
||||
}}>
|
||||
{group.offset + i === activeContainer && <i className='fa fa-angle-right' />}
|
||||
{container.name === containerName && <i className='fa fa-angle-right' />}
|
||||
<span title={container.name}>{container.name}</span>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {DataLoader, Tab, Tabs} from 'argo-ui';
|
||||
import * as React from 'react';
|
||||
import {useState} from 'react';
|
||||
import {EventsList, YamlEditor} from '../../../shared/components';
|
||||
import * as models from '../../../shared/models';
|
||||
import {ErrorBoundary} from '../../../shared/components/error-boundary/error-boundary';
|
||||
@@ -34,6 +35,7 @@ interface ResourceDetailsProps {
|
||||
|
||||
export const ResourceDetails = (props: ResourceDetailsProps) => {
|
||||
const {selectedNode, updateApp, application, isAppSelected, tree} = {...props};
|
||||
const [activeContainer, setActiveContainer] = useState();
|
||||
const appContext = React.useContext(Context);
|
||||
const tab = new URLSearchParams(appContext.history.location.search).get('tab');
|
||||
const selectedNodeInfo = NodeInfo(new URLSearchParams(appContext.history.location.search).get('node'));
|
||||
@@ -86,7 +88,10 @@ export const ResourceDetails = (props: ResourceDetailsProps) => {
|
||||
});
|
||||
}
|
||||
|
||||
const onClickContainer = (group: any, i: number) => SelectNode(selectedNodeKey, group.offset + i, 'logs', appContext);
|
||||
const onClickContainer = (group: any, i: number, activeTab: string) => {
|
||||
setActiveContainer(group.offset + i);
|
||||
SelectNode(selectedNodeKey, activeContainer, activeTab, appContext);
|
||||
};
|
||||
|
||||
if (logsAllowed) {
|
||||
tabs = tabs.concat([
|
||||
@@ -103,7 +108,7 @@ export const ResourceDetails = (props: ResourceDetailsProps) => {
|
||||
name={node.name}
|
||||
namespace={podState.metadata.namespace}
|
||||
applicationName={application.metadata.name}
|
||||
containerName={AppUtils.getContainerName(podState, selectedNodeInfo.container)}
|
||||
containerName={AppUtils.getContainerName(podState, activeContainer)}
|
||||
page={{number: page, untilTimes}}
|
||||
setPage={pageData => appContext.navigation.goto('.', {page: pageData.number, untilTimes: pageData.untilTimes.join(',')})}
|
||||
containerGroups={containerGroups}
|
||||
@@ -121,7 +126,14 @@ export const ResourceDetails = (props: ResourceDetailsProps) => {
|
||||
icon: 'fa fa-terminal',
|
||||
title: 'Terminal',
|
||||
content: (
|
||||
<PodTerminalViewer applicationName={application.metadata.name} projectName={application.spec.project} podState={podState} selectedNode={selectedNode} />
|
||||
<PodTerminalViewer
|
||||
applicationName={application.metadata.name}
|
||||
projectName={application.spec.project}
|
||||
podState={podState}
|
||||
selectedNode={selectedNode}
|
||||
containerName={AppUtils.getContainerName(podState, activeContainer)}
|
||||
onClickContainer={onClickContainer}
|
||||
/>
|
||||
)
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -1071,9 +1071,12 @@ export function parseApiVersion(apiVersion: string): {group: string; version: st
|
||||
return {version: parts[0], group: ''};
|
||||
}
|
||||
|
||||
export function getContainerName(pod: any, containerIndex: number): string {
|
||||
export function getContainerName(pod: any, containerIndex: number | null): string {
|
||||
if (containerIndex == null && pod.metadata?.annotations?.['kubectl.kubernetes.io/default-container']) {
|
||||
return pod.metadata?.annotations?.['kubectl.kubernetes.io/default-container'];
|
||||
}
|
||||
const containers = (pod.spec.containers || []).concat(pod.spec.initContainers || []);
|
||||
const container = containers[containerIndex];
|
||||
const container = containers[containerIndex || 0];
|
||||
return container.name;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user