wip
This commit is contained in:
parent
848b66fa0c
commit
9156119940
4 changed files with 161 additions and 63 deletions
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
};
|
Loading…
Reference in a new issue