query for workflows
This commit is contained in:
parent
f3c473ccf3
commit
617f0053a5
3 changed files with 141 additions and 47 deletions
|
@ -25,6 +25,7 @@
|
|||
"dependencies": {
|
||||
"@backstage/core-components": "^0.12.4",
|
||||
"@backstage/core-plugin-api": "^1.4.0",
|
||||
"@backstage/plugin-catalog-react": "^1.3.0",
|
||||
"@backstage/theme": "^0.2.17",
|
||||
"@material-ui/core": "^4.12.2",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
|
@ -43,8 +44,8 @@
|
|||
"@testing-library/react": "^12.1.3",
|
||||
"@testing-library/user-event": "^14.0.0",
|
||||
"@types/node": "*",
|
||||
"msw": "^0.49.0",
|
||||
"cross-fetch": "^3.1.5"
|
||||
"cross-fetch": "^3.1.5",
|
||||
"msw": "^0.49.0"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
|
|
|
@ -8,38 +8,33 @@ import {
|
|||
Header,
|
||||
Page,
|
||||
Content,
|
||||
ContentHeader,
|
||||
HeaderLabel,
|
||||
SupportButton,
|
||||
} from '@backstage/core-components';
|
||||
import {FetchTFState} from "./FetchTFState";
|
||||
import {FetchTFState, ManageBlueprint} from "./FetchTFState";
|
||||
|
||||
export const BlueprintsComponent = () => (
|
||||
<Page themeId="tool">
|
||||
<Header title="Blueprint information">
|
||||
<HeaderLabel label="Owner" value="Team X" />
|
||||
<HeaderLabel label="Lifecycle" value="Alpha" />
|
||||
</Header>
|
||||
<Content>
|
||||
{/*<ContentHeader title="Blueprint information">*/}
|
||||
{/* <SupportButton>A description of your plugin goes here.</SupportButton>*/}
|
||||
{/*</ContentHeader>*/}
|
||||
<Grid container spacing={3} direction="column">
|
||||
<Grid item>
|
||||
<InfoCard title="Blueprint management">
|
||||
<Typography color="textSecondary">
|
||||
Manage this blueprint deployment
|
||||
</Typography>
|
||||
<IconButton aria-label="delete" size="medium">
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
<IconButton aria-label="clear" size="medium">
|
||||
<ClearIcon />
|
||||
</IconButton>
|
||||
<IconButton aria-label="link" size="medium">
|
||||
<LinkOffRounded />
|
||||
</IconButton>
|
||||
</InfoCard>
|
||||
<ManageBlueprint />
|
||||
{/*<InfoCard title="Blueprint management">*/}
|
||||
{/* <Typography color="textSecondary">*/}
|
||||
{/* Manage this blueprint deployment*/}
|
||||
{/* </Typography>*/}
|
||||
{/* <IconButton aria-label="delete" size="medium">*/}
|
||||
{/* <DeleteIcon />*/}
|
||||
{/* </IconButton>*/}
|
||||
{/* <IconButton aria-label="clear" size="medium">*/}
|
||||
{/* <ClearIcon />*/}
|
||||
{/* </IconButton>*/}
|
||||
{/* <IconButton aria-label="link" size="medium">*/}
|
||||
{/* <LinkOffRounded />*/}
|
||||
{/* </IconButton>*/}
|
||||
{/*</InfoCard>*/}
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<FetchTFState />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Table, TableColumn, Progress } from '@backstage/core-components';
|
||||
import {Table, TableColumn, Progress, InfoCard} from '@backstage/core-components';
|
||||
import Alert from '@material-ui/lab/Alert';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
|
||||
|
@ -10,6 +10,13 @@ import {
|
|||
} from '@backstage/core-plugin-api';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import {gunzipSync} from "zlib";
|
||||
import {useEntity} from "@backstage/plugin-catalog-react"
|
||||
import {IconButton, Typography} from "@material-ui/core";
|
||||
import DeleteIcon from "@material-ui/icons/Delete";
|
||||
import ClearIcon from "@material-ui/icons/Clear";
|
||||
import LinkOffRounded from "@material-ui/icons/LinkOffRounded";
|
||||
|
||||
const token = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxNWQ5MzdiNTViOWE4NjBhN2MzNjY5ZDBjODAzMjZjZjdlNDhmOGUifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjIl0sImV4cCI6MTY3ODI5OTQ2MywiaWF0IjoxNjc4MjEzMDYzLCJpc3MiOiJodHRwczovL29pZGMuZWtzLnVzLXdlc3QtMi5hbWF6b25hd3MuY29tL2lkLzNDRUJBM0NBNzg3MEEzRTVCRkUyQ0YzRkExNzNFRTU2Iiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJhZG1pbiIsInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJhZG1pbiIsInVpZCI6IjQyMzQwOTdiLWFmZjktNDc1Zi05NzY0LTg5NjM4ZWQ4MmVhMiJ9fSwibmJmIjoxNjc4MjEzMDYzLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6YWRtaW46YWRtaW4ifQ.CMew9l09MFBSISOPczcITpz9ZP5XASWlD7ez-tnvfs2ZzhVI7V8OpazQSQSXFcsCs399B3-DHc4Zt6NY9rZgvAMQ9hXtfO2a840o4sRMabOuljS7br503XUPr1JUwkTZ6hS_LRVNDqE8MEw8eyLmKQ7K_jV0fyWsIrR9mVXn6RVhD96P_k-N5da49MP-PbFHJsEeOwVwcUCWRfPYIMp1XlpCGxjqymKnxVQFuVC76aQYpSKzOsI-rYMkCk0Yt7L-NjOpx0tsBvs58SJy5XP_x64cw0_j4Xba9prH8g4OmGeCUV5csaT8N3FaY0e_kGqftY-B2bwtOxl0vx_6gadjyQ"
|
||||
|
||||
type TFState = {
|
||||
terraform_version: string
|
||||
|
@ -59,10 +66,10 @@ export const TFTable = (props: TFTableProps) => {
|
|||
}
|
||||
|
||||
export const FetchTFState = () => {
|
||||
const discoveryApi = useApi(discoveryApiRef);
|
||||
const apiRef = useApi(discoveryApiRef)
|
||||
const { value, loading, error } = useAsync((): Promise<TFState> => {
|
||||
return getTFState("tfstate-default-helloworld", "flux-system", discoveryApi)
|
||||
} )
|
||||
return getTFState("tfstate-default-helloworld", "flux-system", apiRef)
|
||||
})
|
||||
if (loading) {
|
||||
return <Progress />
|
||||
} else if (error) {
|
||||
|
@ -85,26 +92,19 @@ export const FetchTFState = () => {
|
|||
})
|
||||
|
||||
return <TFTable resources={resources}/>
|
||||
|
||||
// const { value, loading, error } = useAsync(async (): Promise<User[]> => {
|
||||
// const response = await fetch('https://randomuser.me/api/?results=20');
|
||||
// const data = await response.json();
|
||||
// return data.results;
|
||||
// }, []);
|
||||
//
|
||||
// if (loading) {
|
||||
// return <Progress />;
|
||||
// } else if (error) {
|
||||
// return <Alert severity="error">{error.message}</Alert>;
|
||||
// }
|
||||
//
|
||||
// return <DenseTable users={value || []} />;
|
||||
};
|
||||
|
||||
|
||||
// horrible
|
||||
type payload = {
|
||||
kind: string
|
||||
apiVersion: string
|
||||
items?: {
|
||||
metadata: {
|
||||
labels: {
|
||||
[key: string]: string
|
||||
}
|
||||
}
|
||||
}[]
|
||||
metadata: {
|
||||
annotations: {
|
||||
[key: string]: string
|
||||
|
@ -116,15 +116,15 @@ type payload = {
|
|||
}
|
||||
}
|
||||
|
||||
async function getTFState(name: string, namespace: string, discoveryApi: DiscoveryApi): Promise<TFState> {
|
||||
const kubernetesBaseUrl = await discoveryApi.getBaseUrl('kubernetes');
|
||||
const kubernetesProxyEndpoint = `${kubernetesBaseUrl}/proxy`;
|
||||
async function getTFState(name: string, namespace: string, apiRef: DiscoveryApi): Promise<TFState> {
|
||||
const baseUrl = await apiRef.getBaseUrl("kubernetes")
|
||||
const proxyUrl = `${baseUrl}/proxy`
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const resp = await fetch(`${kubernetesProxyEndpoint}/api/v1/namespaces/${namespace}/secrets/${name}`, {
|
||||
const resp = await fetch(`${proxyUrl}/api/v1/namespaces/${namespace}/secrets/${name}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'X-Kubernetes-Cluster': "canoe-packaging",
|
||||
Authorization: `Bearer TOKEN`,
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
if (resp.ok) {
|
||||
|
@ -145,4 +145,102 @@ async function getTFState(name: string, namespace: string, discoveryApi: Discove
|
|||
})
|
||||
}
|
||||
|
||||
enum workflowStatus {
|
||||
UNKNOWN,
|
||||
DELETING = 0,
|
||||
CREATING,
|
||||
DELETED,
|
||||
NOTFOUND,
|
||||
FAILED
|
||||
}
|
||||
export const ManageBlueprint = () => {
|
||||
const entity = useEntity()
|
||||
const apiRef = useApi(discoveryApiRef)
|
||||
const { value, loading, error } = useAsync((): Promise<workflowStatus> => {
|
||||
return getWorkflow(entity.entity.metadata.uid!, "admin", apiRef)
|
||||
})
|
||||
if (loading) {
|
||||
return <Progress />
|
||||
} else if (error) {
|
||||
return <Alert severity="error">{error}</Alert>;
|
||||
}
|
||||
let text: string
|
||||
switch (value) {
|
||||
case workflowStatus.DELETING:
|
||||
text = "This blueprint deployment is being deleted"
|
||||
break
|
||||
case workflowStatus.DELETED:
|
||||
text = "This blueprint deployment was successfully deleted"
|
||||
break
|
||||
case workflowStatus.NOTFOUND:
|
||||
text = "Manage this blueprint with the buttons below"
|
||||
break
|
||||
case workflowStatus.FAILED:
|
||||
return <Alert severity="error">"failed to delete blueprint deployment"</Alert>;
|
||||
default:
|
||||
return <Alert severity="error">"could not determine blueprint status"</Alert>;
|
||||
}
|
||||
return (
|
||||
<InfoCard title="Blueprint management">
|
||||
<Typography color="textSecondary">
|
||||
{text}
|
||||
</Typography>
|
||||
<IconButton aria-label="delete" size="medium">
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
<IconButton aria-label="clear" size="medium">
|
||||
<ClearIcon />
|
||||
</IconButton>
|
||||
<IconButton aria-label="link" size="medium">
|
||||
<LinkOffRounded />
|
||||
</IconButton>
|
||||
</InfoCard>
|
||||
)
|
||||
}
|
||||
async function getWorkflow(entityId: string, namespace: string, apiRef: DiscoveryApi): Promise<workflowStatus> {
|
||||
const baseUrl = await apiRef.getBaseUrl("kubernetes")
|
||||
const proxyUrl = `${baseUrl}/proxy`
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const queryParams = new URLSearchParams({
|
||||
labelSelector: `entity-id=${entityId}`,
|
||||
limit: "1"
|
||||
}).toString()
|
||||
|
||||
const resp = await fetch(`${proxyUrl}/apis/argoproj.io/v1alpha1/namespaces/${namespace}/workflows?${queryParams}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'X-Kubernetes-Cluster': "canoe-packaging",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
if (resp.ok) {
|
||||
const payload = await resp.json() as payload
|
||||
if (payload.items!.length > 0) {
|
||||
const labels = payload.items![0].metadata.labels
|
||||
if ("workflows.argoproj.io/phase" in labels) {
|
||||
switch (labels["workflows.argoproj.io/phase"]) {
|
||||
case "Running":
|
||||
resolve(workflowStatus.DELETING)
|
||||
break;
|
||||
case "Succeeded":
|
||||
resolve(workflowStatus.DELETED)
|
||||
break
|
||||
case "Failed":
|
||||
resolve(workflowStatus.FAILED)
|
||||
break
|
||||
default:
|
||||
reject(workflowStatus.UNKNOWN)
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resolve(workflowStatus.NOTFOUND)
|
||||
}
|
||||
} else {
|
||||
reject(`Failed to retrieve terraform information: ${resp.status}: ${resp.statusText} `)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue