Skip to content

Commit

Permalink
Merge pull request #2 from ilan-pinto/patternfly-klusterlet
Browse files Browse the repository at this point in the history
feat: klusterlet and dashboard fixes
Signed-off-by: Ilan Pinto <[email protected]>
  • Loading branch information
ilan-pinto committed Jul 26, 2023
2 parents 4ef114e + daac146 commit 92c5166
Show file tree
Hide file tree
Showing 11 changed files with 227 additions and 100 deletions.
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@
"out": true // set this to false to include "out" folder in search results
},
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
"typescript.tsc.autoDetect": "off"
"typescript.tsc.autoDetect": "off",
"cSpell.words": [
"klusterlet"
]
}
12 changes: 4 additions & 8 deletions webview-ui/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import React from "react";
import ShowSelectedContext from "./comp/SelectedContext";
import ShowKlusterlets from "./comp/Klusterlets";
import ShowAppliedManifestWorks from "./comp/AppliedManifestWorks";
import ShowSubscriptionStatuses from "./comp/SubscriptionStatuses";

import OcmHeader from "./comp/Header";
import { Page, PageSection } from "@patternfly/react-core";
import ClusterManagerPage from "./parent/clusterManagerParent";
import ManagedClusterPage from "./parent/managedClusterParent";



Expand All @@ -20,11 +19,8 @@ export default class App extends React.Component {
header= { <OcmHeader /> } >
<PageSection style={{ color: "black" }}>
<ShowSelectedContext/>
<ClusterManagerPage/>

<ShowKlusterlets/>
<ShowAppliedManifestWorks/>
<ShowSubscriptionStatuses/>
<ClusterManagerPage/>
<ManagedClusterPage/>
</PageSection>
</Page>
)
Expand Down
12 changes: 7 additions & 5 deletions webview-ui/src/common/Graph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const resourceTranslationMap:ResourceObject = {
configmap: 'cm',
secret: 'secret',
ingress: 'ing',
serviceaccount: 'sa',
serviceaccount: 'sa',
cronjob: 'cronjob',
endpoint: 'ep',
limitrange: 'limits',
Expand Down Expand Up @@ -67,14 +67,16 @@ export const Graph: React.FC<GraphProps> = ({ data ,images }) => {
namespace: data.namespace,
children: data.children.map(mf => {
images.forEach( (image: kubeImage) => {
let field = mf.kind.toLowerCase()
let shortKind = resourceTranslationMap[field]
if (shortKind === image.name.toLowerCase()) {
if (resourceTranslationMap[mf.kind.toLowerCase()] === image.name.toLowerCase()) {
mf.icon = image.uri
return mf
}
else if (resourceTranslationMap[mf.kind.toLowerCase().slice(0, -1)] === image.name.toLowerCase()) {
mf.icon = image.uri
return mf
}
return mf
})
})
return mf
})
}
Expand Down
52 changes: 34 additions & 18 deletions webview-ui/src/comp/AppliedManifestWorks.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,61 @@
import { useState, useEffect } from 'react';
import { OcmResource } from '../../../src/data/loader'
import { Gallery, Title } from '@patternfly/react-core';
import GalleryTableComponent from '../common/ConditionTable';
import {DateFormat} from '../common/common'
export default function ShowAppliedManifestWorks() {
let [appliedManifestWorks, setAppliedManifestWorks] = useState<OcmResource[]>([]);
import {DateFormat, kubeImage} from '../common/common'
import Graph from '../common/Graph';

useEffect(() => {
window.addEventListener("message", event => {
if ('crsDistribution' in event.data.msg && 'AppliedManifestWork' === event.data.msg.crsDistribution.kind) {
setAppliedManifestWorks(JSON.parse(event.data.msg.crsDistribution.crs));
}
});
});

const AppliedResourcesColumn: Object[] = [

type AppliedManifestWorksProps = {
appliedManifestWorks: OcmResource[],
kubeImages: kubeImage[]
}

export default function ShowAppliedManifestWorks(Props:AppliedManifestWorksProps) {


const AppliedResourcesColumn: Object[] = [
{title: "Resource Name",},
{title: "Resource"},
{title: "Group" , },
{title: "Namespace" }
]
return (
<section className="component-row">
{ appliedManifestWorks.length > 0 &&
<>
{ Props.appliedManifestWorks.length > 0 &&
<>

<Title headingLevel='h2' size='md' style={{ marginTop: '40px' }}>Applied ManifestWorks</Title>
<Gallery className='ocm-gallery' hasGutter={true} >
{appliedManifestWorks.map(appliedManifestWork => {
{Props.appliedManifestWorks.map(appliedManifestWork => {
console.log(`appliedManifestWork`)
console.log(appliedManifestWork)
const row = appliedManifestWork.kr.status.appliedResources.map( (resource:any) => {
return [ resource.name, resource.resource, resource.group, resource.namespace]
})

return <GalleryTableComponent
title={`ManifestWork Name: ${appliedManifestWork.kr.spec.manifestWorkName}`}
subtitle={`Creation TimeStamp: ${new Date(appliedManifestWork.kr.metadata.creationTimestamp).toLocaleString("en-US",DateFormat)}`}
rows={row}
cells={AppliedResourcesColumn}
sort={{index: 1, direction:"asc"}}
id={`${appliedManifestWork.kr.spec.manifestWorkName}`}
/>
>
<Graph data={{ name: appliedManifestWork.kr.spec.manifestWorkName,
namespace: appliedManifestWork.kr.metadata.namespace?appliedManifestWork.kr.metadata.namespace:'missing namespace',
children: appliedManifestWork.kr.status.appliedResources.map( (appliedResources:any) => {

return {
group: appliedResources.group,
name: appliedResources.name,
namespace: appliedResources.namespace,
kind: appliedResources.resource,
version: appliedResources.version
}
})
} } images={Props.kubeImages}
/>
</GalleryTableComponent>
}
)}
</Gallery>
Expand Down
37 changes: 30 additions & 7 deletions webview-ui/src/comp/ClusterManagerDashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Panel, PanelMain, PanelMainBody } from "@patternfly/react-core"
import { Divider, Flex, FlexItem, Icon, Panel, PanelMain, PanelMainBody } from "@patternfly/react-core"
import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon'
import TopologyIcon from '@patternfly/react-icons/dist/esm/icons/topology-icon'
import { OcmResource } from "../../../src/data/loader"
import { kubeImage } from "../common/common"

Expand All @@ -21,14 +23,35 @@ type ClusterManagerDashboardProps = {
export default function ClusterManagerDashboard( Props: ClusterManagerDashboardProps) {

return(
<Panel>
<Panel variant="raised">
{ (Props.data.clusterManagers && Props.data.clusterManagers.length > 0) &&
<PanelMain>
<PanelMainBody>
{ Props.data.clusterManagers?<p> Hub Clusters: {Props.data.clusterManagers.length} </p>:null}
{ Props.data.managedClusters?<p> Managed Clusters: {Props.data.managedClusters.length} </p>:null}
{ Props.data.managedClusterSets?<p> managedClusterSets: {Props.data.managedClusterSets.length} </p>:null}
{ Props.data.placements?<p> Placements: {Props.data.placements.length} </p>:null}
<PanelMainBody>
<Flex>
<FlexItem>
<Icon>
<CubeIcon/>
</Icon>
{ Props.data.clusterManagers?<p> Hub Clusters: {Props.data.clusterManagers.length} </p>:null}
{ Props.data.managedClusters?<p> Managed Clusters: {Props.data.managedClusters.length} </p>:null}

</FlexItem>
<Divider
component="div"
orientation={{
default: 'vertical'
}
}
/>
<FlexItem>
<Icon>
<TopologyIcon/>
</Icon>
{ Props.data.placements?<p> Placements: {Props.data.placements.length} </p>:null}
{ Props.data.managedClusterSets?<p> managedClusterSets: {Props.data.managedClusterSets.length} </p>:null}

</FlexItem>
</Flex>
</PanelMainBody>
</PanelMain>
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import { useState, useEffect } from 'react';
import { OcmResource } from '../../../src/data/loader'
import { ConditionTableComponent } from '../common/ConditionTable';
import { DateFormat } from '../common/common';
import { OcmLabels } from '../common/Labels';

export default function ShowKlusterlets() {
let [klusterlets, setKlusterlets] = useState<OcmResource[]>([]);
type klusterletProps = {
klusterlet: OcmResource[]
}

export default function ShowKlusterlet(Props: klusterletProps) {


useEffect(() => {
window.addEventListener("message", event => {
if ('crsDistribution' in event.data.msg && 'Klusterlet' === event.data.msg.crsDistribution.kind) {
setKlusterlets(JSON.parse(event.data.msg.crsDistribution.crs));
}
});
});

const row = klusterlets.map(klusterlet => {
const row = Props.klusterlet.map(klusterlet => {
return klusterlet.kr.status.conditions.map( (condition:any) => {
return [new Date(condition.lastTransitionTime).toLocaleString("en-US",DateFormat),
condition.message,
Expand All @@ -26,11 +22,11 @@ export default function ShowKlusterlets() {
})
return (
//TODO-Add panel
//TODO-add clusterlet dashboard
//TODO-add Klusterlet dashboard
<section className="component-row">
{ klusterlets.length > 0 &&
{ Props.klusterlet.length > 0 &&
<>
{klusterlets.map(klusterlet => {
{Props.klusterlet.map(klusterlet => {
return <>
<ConditionTableComponent id='' title={`${klusterlet.kr.metadata.name}` } rows={ row[0]} />
{klusterlet.kr.metadata.labels?<OcmLabels labels={klusterlet.kr.metadata.labels} />:null }
Expand Down
2 changes: 0 additions & 2 deletions webview-ui/src/comp/ManagedClusterSets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ export default function ShowManagedClusterSets(Props: managedClusterSetsProps) {
<Gallery className='ocm-gallery' hasGutter={true} >

{Props.managedClusterSets.map(managedClusterSet => {
console.log(`managedClusterSet`)
console.log(managedClusterSet)
const code = yaml.dump(managedClusterSet.kr.spec.clusterSelector)
const row = managedClusterSet.kr.status.conditions.map( (condition:any) => {
return [new Date(condition.lastTransitionTime).toLocaleString("en-US",DateFormat),
Expand Down
29 changes: 16 additions & 13 deletions webview-ui/src/comp/SubscriptionReports.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,19 @@ export default function ShowSubscriptionReports(Props: SubscriptionReportsProps)
<Gallery className='ocm-gallery' hasGutter={true} >

{Props.subscriptionReports.map( subscriptionReport => {
const rows = [[subscriptionReport.kr.summary.clusters,
subscriptionReport.kr.summary.deployed,
subscriptionReport.kr.summary.failed,
subscriptionReport.kr.summary.inProgress,
subscriptionReport.kr.summary.propagationFailed
]]

console.log(rows)
console.log(`subscriptionReport`)
console.log(subscriptionReport)

let rows = [[0,0,0,0,0]]

if (subscriptionReport.kr.summary && subscriptionReport.kr.summary.clusters > -1 ) {
rows = [[subscriptionReport.kr.summary.clusters,
subscriptionReport.kr.summary.deployed,
subscriptionReport.kr.summary.failed,
subscriptionReport.kr.summary.inProgress,
subscriptionReport.kr.summary.propagationFailed
]]
}

return <GalleryItem>
<Card>
Expand All @@ -45,21 +50,19 @@ export default function ShowSubscriptionReports(Props: SubscriptionReportsProps)
<Title headingLevel='h3' size='md'>Namespace: {subscriptionReport.kr.metadata.namespace?subscriptionReport.kr.metadata.namespace:'missing namespace'}</Title>
</CardHeader>
<CardBody>

<p> Report Type: {subscriptionReport.kr.reportType}</p>
{/*TODO add placement name and chanel */}
<Graph data={{ name: subscriptionReport.kr.metadata.name,
namespace: subscriptionReport.kr.metadata.namespace?subscriptionReport.kr.metadata.namespace:'missing namespace',
children: subscriptionReport.kr.resources
children: subscriptionReport.kr.resources?subscriptionReport.kr.resources:[]
} } images={Props.kubeImages}/>
<div style={{ borderTop: "1px solid #fff ", marginLeft: 10, marginRight: 10 }}></div>
<Table gridBreakPoint= 'grid-md' rows={rows} cells={SubscriptionReportsSummeryColumns} >
<TableHeader/>
<TableBody />
</Table>

</CardBody>



</Card>
</GalleryItem>
})}
Expand Down
64 changes: 37 additions & 27 deletions webview-ui/src/comp/SubscriptionStatuses.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,49 @@
import { VSCodeDataGrid, VSCodeDataGridCell, VSCodeDataGridRow, } from '@vscode/webview-ui-toolkit/react';
import { useState, useEffect } from 'react';
import { OcmResource } from '../../../src/data/loader'
import { Title } from '@patternfly/react-core';
import { Gallery, Title } from '@patternfly/react-core';
import GalleryTableComponent from '../common/ConditionTable';

export default function ShowSubscriptionStatuses() {
let [subscriptionStatuses, setSubscriptionStatuses] = useState<OcmResource[]>([]);
type SubscriptionStatusesProps ={
subscriptionStatuses: OcmResource[],
subscription: OcmResource[],
}

useEffect(() => {
window.addEventListener("message", event => {
if ('crsDistribution' in event.data.msg && 'SubscriptionStatus' === event.data.msg.crsDistribution.kind) {
setSubscriptionStatuses(JSON.parse(event.data.msg.crsDistribution.crs));
}
});
});
const SubscriptionStatusesColumns: Object[] = [
{title: "kind" ,},
{title: "LastUpdateTime", },
{title: "Name" },
{title: "Namespace" },
{title: "PropagationFailed" }
]

export default function ShowSubscriptionStatuses(Props: SubscriptionStatusesProps) {

return (
<section className="component-row">
{ subscriptionStatuses.length >0 &&
{ Props.subscriptionStatuses.length >0 &&
<>
<Title headingLevel='h2' size='md' style={{ marginTop: '40px' }}>Subscription Status</Title>
<VSCodeDataGrid gridTemplateColumns="1fr 1fr" aria-label='SubscriptionStatus' >
<VSCodeDataGridRow rowType="sticky-header">
<VSCodeDataGridCell cellType='columnheader' gridColumn='1'>Subscription Name</VSCodeDataGridCell>
<VSCodeDataGridCell cellType='columnheader' gridColumn='2'>Report Type</VSCodeDataGridCell>
</VSCodeDataGridRow>

{subscriptionStatuses.map(subscriptionStatus => {
return <VSCodeDataGridRow>
<VSCodeDataGridCell gridColumn='1' >{subscriptionStatus.kr.metadata.name}</VSCodeDataGridCell>
<VSCodeDataGridCell gridColumn='2'>{subscriptionStatus.kr.statuses.packages.map( ( pkg:any )=> { return<p> - kind: {pkg.kind}, lastUpdateTime: {pkg.lastUpdateTime}, name: {pkg.name}, namespace: {pkg.namespace}, phase: {pkg.phase} </p> })} </VSCodeDataGridCell>
</VSCodeDataGridRow>
} )
}
</VSCodeDataGrid>
<Gallery className='ocm-gallery' hasGutter={true} >
{Props.subscriptionStatuses.map(subscriptionStatus => {
console.log(`subscriptionStatus`)
console.log(subscriptionStatus)
return <GalleryTableComponent
title={`Subscription Name: ${subscriptionStatus.name}`}
rows={subscriptionStatus.kr.statuses.packages.map( ( pkg:any )=> {return [ pkg.kind,
pkg.lastUpdateTime,
pkg.name,
pkg.namespace,
pkg.phase
]}
) }
cells={SubscriptionStatusesColumns}
id={`${subscriptionStatus.kr.metadata.name}`}
>
<p> Namespace: {subscriptionStatus.namespace} </p>
</GalleryTableComponent>
}
)}
<div style={{ borderTop: "1px solid #fff ", marginLeft: 10, marginRight: 10 }}></div>
</Gallery>
</>
}
</section>
Expand Down
Loading

0 comments on commit 92c5166

Please sign in to comment.