This commit is contained in:
Manabu Mccloskey 2023-07-06 14:06:12 -07:00
parent 848b66fa0c
commit 9156119940
4 changed files with 161 additions and 63 deletions

View file

@ -8,42 +8,44 @@ export type Metadata = {
};
export type Spec = {
arguments: string[];
batchScheduler: string;
arguments?: string[];
batchScheduler?: string;
driver: {
coreLimit: string;
coreRequest: string;
cores: number;
gpu: {
coreLimit?: string;
coreRequest?: string;
cores?: number;
gpu?: {
name: string;
quantity: number;
};
labels: Record<string, string>;
memory: string;
memoryOverhead: string;
podName: string;
schedulerName: string;
serviceAccount: string;
labels?: Record<string, string>;
memory?: string;
memoryOverhead?: string;
podName?: string;
schedulerName?: string;
serviceAccount?: string;
};
executor: {
coreLimit: string;
coreRequest: string;
cores: number;
gpu: {
coreLimit?: string;
coreRequest?: string;
cores?: number;
gpu?: {
name: string;
quantity: number;
};
instances: number;
labels: Record<string, string>;
memory: string;
memoryOverhead: string;
schedulerName: string;
serviceAccount: string;
instances?: number;
labels?: Record<string, string>;
memory?: string;
memoryOverhead?: string;
schedulerName?: string;
serviceAccount?: string;
};
image: string;
mainClass: string;
mainClass?: string;
mainApplicationFile?: string;
mode: string;
pythonVersion: string;
pythonVersion?: string;
sparkVersion: string;
type: string;
};

View file

@ -1,7 +1,7 @@
import { useApi } from '@backstage/core-plugin-api';
import { apacheSparkApiRef } from '../../api';
import useAsync from 'react-use/lib/useAsync';
import { ApacheSpark, ApacheSparkList } from '../../api/model';
import { ApacheSpark } from '../../api/model';
import {
LogViewer,
Progress,
@ -75,9 +75,7 @@ export const ApacheSparkExecutorLogs = (props: { sparkApp: ApacheSpark }) => {
}
const handleChange = (item: SelectedItems) => {
// setSelected(item);
// return;
if (typeof item === 'string' && item !== '' && item !== '[]') {
if (typeof item === 'string' && item !== '') {
setSelected(item);
}
};
@ -89,7 +87,7 @@ export const ApacheSparkExecutorLogs = (props: { sparkApp: ApacheSpark }) => {
items={executors}
onChange={handleChange}
/>
{ExecutorLogs({ name: selected })}
<ExecutorLogs name={selected} key={selected} />
</>
);
};

View file

@ -4,19 +4,18 @@ import {
createStyles,
IconButton,
makeStyles,
Paper,
Theme,
Typography,
} from '@material-ui/core';
import Close from '@material-ui/icons/Close';
import React, { PropsWithChildren } from 'react';
import React from 'react';
import { stringify } from 'yaml';
import { CopyTextButton, TabbedLayout } from '@backstage/core-components';
import { MemoryRouter, Route, Routes } from 'react-router-dom';
import {
ApacheSparkDriverLogs,
ApacheSparkExecutorLogs,
} from '../ApacheSparkLogs/ApacheSparkLogs';
import { DrawerOverview } from './DrawerOverview';
const useDrawerContentStyles = makeStyles((theme: Theme) =>
createStyles({
@ -36,7 +35,12 @@ const useDrawerContentStyles = makeStyles((theme: Theme) =>
},
logs: {
height: 500,
backgroundColor: '#EEEEEE',
display: 'flex',
flexDirection: 'column',
flexShrink: 0,
},
logs2: {
height: 600,
display: 'flex',
flexDirection: 'column',
},
@ -57,7 +61,14 @@ export const DrawerContent = ({
const yamlString = stringify(apacheSpark);
return (
<TabbedLayout>
<TabbedLayout.Route path="/" title="Manifest">
<TabbedLayout.Route path="/" title="Overview">
<>
<div>
<DrawerOverview sparkApp={apacheSpark} />
</div>
</>
</TabbedLayout.Route>
<TabbedLayout.Route path="/manifests" title="Manifest">
<>
<div className={classes.header}>
<Typography variant="h6">{apacheSpark.metadata.name}</Typography>
@ -74,40 +85,25 @@ export const DrawerContent = ({
<CopyTextButton text={yamlString} tooltipText="Copy" />
<pre>{yamlString}</pre>
</div>
<div>
<Button
variant="contained"
color="primary"
onClick={() => toggleDrawer(false)}
>
Primary Action
</Button>
<Button
className={classes.secondaryAction}
variant="outlined"
color="primary"
onClick={() => toggleDrawer(false)}
>
Secondary Action
</Button>
</div>
</>
</TabbedLayout.Route>
<TabbedLayout.Route path="/logs" title="Logs">
<>
<div className={classes.logs}>
<Typography variant="h6">
Driver Log for {apacheSpark.metadata.name}
</Typography>
{/*<ApacheSparkDriverLogs sparkApp={apacheSpark} />*/}
<div className={classes.logs2}>
<div className={classes.logs}>
<Typography variant="h6">
Driver Log for {apacheSpark.metadata.name}
</Typography>
<ApacheSparkDriverLogs sparkApp={apacheSpark} />
</div>
</div>
<div className={classes.logs}>
<Typography variant="h6">
Executor Logs for {apacheSpark.metadata.name}
</Typography>
<ApacheSparkExecutorLogs
sparkApp={apacheSpark}
></ApacheSparkExecutorLogs>
<div className={classes.logs2}>
<div className={classes.logs}>
<Typography variant="h6">
Executor Logs for {apacheSpark.metadata.name}
</Typography>
<ApacheSparkExecutorLogs sparkApp={apacheSpark} />
</div>
</div>
</>
</TabbedLayout.Route>

View file

@ -0,0 +1,102 @@
import { createStyles, makeStyles, Theme } from '@material-ui/core';
import { ApacheSpark } from '../../api/model';
import {
InfoCard,
StatusError,
StatusOK,
StatusPending,
StatusRunning,
StructuredMetadataTable,
} from '@backstage/core-components';
import React from 'react';
const useStyles = makeStyles(() =>
createStyles({
content: {
justifyContent: 'space-between',
display: 'flex',
flexDirection: 'column',
padding: '5px',
gap: '30px',
},
}),
);
type generateMetadataOutput = {
app: { [key: string]: any };
driver: { [key: string]: any };
executor: { [key: string]: any };
};
function generateMetadata(sparkApp: ApacheSpark): generateMetadataOutput {
const out = {} as generateMetadataOutput;
const executor: { [key: string]: any } = {};
const app: { [key: string]: any } = {
name: sparkApp.metadata.name,
namespace: sparkApp.metadata.namespace,
status: renderState(sparkApp.status.applicationState.state),
image: sparkApp.spec.image,
mode: sparkApp.spec.mode,
};
if (sparkApp.status.applicationState.errorMessage)
app['error Message'] = sparkApp.status.applicationState.errorMessage;
for (const key in sparkApp.status.executorState) {
if (sparkApp.status.executorState.hasOwnProperty(key)) {
executor[`${key}`] = renderState(sparkApp.status.executorState[key]);
}
}
out.app = app;
out.driver = sparkApp.status.driverInfo;
out.executor = executor;
return out;
}
function renderState(state: string): JSX.Element {
switch (state) {
case 'RUNNING':
return <StatusRunning>{state}</StatusRunning>;
case 'COMPLETED':
return <StatusOK>{state}</StatusOK>;
case 'SUBMITTED':
case 'PENDING_RERUN':
return <StatusPending>{state}</StatusPending>;
case 'FAILED':
case 'SUBMISSION_FAILED':
return <StatusError>{state}</StatusError>;
default:
return <StatusPending>{state}</StatusPending>;
}
}
const upperCaseFirstChar = (s: string) => {
if (s.length > 0) {
return `${s.charAt(0).toUpperCase()}${s.slice(1)}`;
}
return s;
};
export const DrawerOverview = (props: { sparkApp: ApacheSpark }) => {
return (
<div className={useStyles().content}>
<InfoCard title="Apache Spark Application">
<StructuredMetadataTable
metadata={generateMetadata(props.sparkApp).app}
options={{ titleFormat: upperCaseFirstChar }}
/>
</InfoCard>
<InfoCard title="Driver">
<StructuredMetadataTable
metadata={generateMetadata(props.sparkApp).driver}
options={{ titleFormat: upperCaseFirstChar }}
/>
</InfoCard>
<InfoCard title="Executors">
<StructuredMetadataTable
metadata={generateMetadata(props.sparkApp).executor}
options={{ titleFormat: upperCaseFirstChar }}
/>
</InfoCard>
</div>
);
};