add workflow templates component
This commit is contained in:
parent
b64e6c821f
commit
a48fe8e471
13 changed files with 446 additions and 56 deletions
|
@ -50,6 +50,9 @@ const overviewContent = (
|
|||
<Grid item md={6}>
|
||||
<EntityArgoWorkflowsOverviewCard />
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<EntityArgoWorkflowsTemplateOverviewCard />
|
||||
</Grid>
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
...
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { DiscoveryApi, FetchApi } from "@backstage/core-plugin-api";
|
||||
import { KubernetesApi } from "@backstage/plugin-kubernetes";
|
||||
import { IoArgoprojWorkflowV1alpha1WorkflowList } from "./generated";
|
||||
import {
|
||||
IoArgoprojWorkflowV1alpha1WorkflowList,
|
||||
IoArgoprojWorkflowV1alpha1WorkflowTemplateList,
|
||||
} from "./generated";
|
||||
import { ArgoWorkflowsApi } from "./index";
|
||||
|
||||
const API_VERSION = "argoproj.io/v1alpha1";
|
||||
|
@ -27,7 +30,7 @@ export class ArgoWorkflows implements ArgoWorkflowsApi {
|
|||
|
||||
async getWorkflowsFromK8s(
|
||||
clusterName: string | undefined,
|
||||
namespace: string | undefined,
|
||||
namespace: string,
|
||||
labels: string | undefined
|
||||
): Promise<IoArgoprojWorkflowV1alpha1WorkflowList> {
|
||||
const ns = namespace !== undefined ? namespace : "default";
|
||||
|
@ -69,32 +72,37 @@ export class ArgoWorkflows implements ArgoWorkflowsApi {
|
|||
return this.getWorkflowsFromProxy(namespace, labels);
|
||||
}
|
||||
|
||||
async getWorkflowTemplates(
|
||||
clusterName: string | undefined,
|
||||
namespace: string,
|
||||
labels: string | undefined
|
||||
): Promise<IoArgoprojWorkflowV1alpha1WorkflowTemplateList> {
|
||||
if (clusterName) {
|
||||
return Promise.reject("t");
|
||||
}
|
||||
return this.getWorkflowTemplatesFromProxy(namespace, labels);
|
||||
}
|
||||
|
||||
async getWorkflowsFromProxy(
|
||||
namespace: string | undefined,
|
||||
namespace: string,
|
||||
labels: string | undefined
|
||||
): Promise<IoArgoprojWorkflowV1alpha1WorkflowList> {
|
||||
const proxyUrl = await this.discoveryApi.getBaseUrl("proxy");
|
||||
const path = `/api/v1/workflows/${namespace}`;
|
||||
const resp = await this.fetchFromPath(path, labels);
|
||||
return await checkAndReturn<IoArgoprojWorkflowV1alpha1WorkflowTemplateList>(
|
||||
resp
|
||||
);
|
||||
}
|
||||
|
||||
const ns = namespace !== undefined ? namespace : "default";
|
||||
const url = `${proxyUrl}${DEFAULT_WORKFLOW_PROXY}/api/v1/workflows/${ns}`;
|
||||
async getWorkflowTemplatesFromProxy(
|
||||
namespace: string,
|
||||
labels: string | undefined
|
||||
): Promise<IoArgoprojWorkflowV1alpha1WorkflowTemplateList> {
|
||||
const path = `/api/v1/workflow-templates/${namespace}`;
|
||||
|
||||
const query = new URLSearchParams({ [API_TIMEOUT]: "30" });
|
||||
if (labels) {
|
||||
query.set(API_LABEL_SELECTOR, labels);
|
||||
}
|
||||
const resp = await this.fetchApi.fetch(`${url}?${query.toString()}`, {});
|
||||
|
||||
if (!resp.ok) {
|
||||
return Promise.reject(
|
||||
`failed to fetch resources: ${resp.status}, ${
|
||||
resp.statusText
|
||||
}, ${await resp.text()}`
|
||||
);
|
||||
}
|
||||
|
||||
// need validation
|
||||
return Promise.resolve(
|
||||
JSON.parse(await resp.text()) as IoArgoprojWorkflowV1alpha1WorkflowList
|
||||
const resp = await this.fetchFromPath(path, labels);
|
||||
return await checkAndReturn<IoArgoprojWorkflowV1alpha1WorkflowTemplateList>(
|
||||
resp
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -105,4 +113,29 @@ export class ArgoWorkflows implements ArgoWorkflowsApi {
|
|||
}
|
||||
return Promise.reject("no clusters found in configuration");
|
||||
}
|
||||
|
||||
async fetchFromPath(
|
||||
path: string,
|
||||
labels: string | undefined
|
||||
): Promise<Response> {
|
||||
const proxyUrl = await this.discoveryApi.getBaseUrl("proxy");
|
||||
const url = `${proxyUrl}${DEFAULT_WORKFLOW_PROXY}${path}`;
|
||||
const query = new URLSearchParams({ [API_TIMEOUT]: "30" });
|
||||
if (labels) {
|
||||
query.set(API_LABEL_SELECTOR, labels);
|
||||
}
|
||||
return this.fetchApi.fetch(`${url}?${query.toString()}`, {});
|
||||
}
|
||||
}
|
||||
|
||||
async function checkAndReturn<T>(resp: Response): Promise<T> {
|
||||
if (!resp.ok) {
|
||||
return Promise.reject(
|
||||
`failed to fetch resources: ${resp.status}, ${
|
||||
resp.statusText
|
||||
}, ${await resp.text()}`
|
||||
);
|
||||
}
|
||||
// need validation
|
||||
return Promise.resolve(JSON.parse(await resp.text()) as T);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { createApiRef } from "@backstage/core-plugin-api";
|
||||
|
||||
import { IoArgoprojWorkflowV1alpha1WorkflowList } from "./generated/";
|
||||
import {
|
||||
IoArgoprojWorkflowV1alpha1WorkflowList,
|
||||
IoArgoprojWorkflowV1alpha1WorkflowTemplateList,
|
||||
} from "./generated/";
|
||||
|
||||
export { ArgoWorkflows } from "./ArgoWorkflows";
|
||||
|
||||
|
@ -8,18 +11,14 @@ export const argoWorkflowsApiRef = createApiRef<ArgoWorkflowsApi>({
|
|||
id: "plugin.argoworkflows",
|
||||
});
|
||||
export interface ArgoWorkflowsApi {
|
||||
getWorkflowsFromK8s(
|
||||
clusterName: string,
|
||||
namespace: string | undefined,
|
||||
labels: string | undefined
|
||||
): Promise<IoArgoprojWorkflowV1alpha1WorkflowList>;
|
||||
getWorkflows(
|
||||
clusterName: string | undefined,
|
||||
namespace: string | undefined,
|
||||
labels: string | undefined
|
||||
): Promise<IoArgoprojWorkflowV1alpha1WorkflowList>;
|
||||
getWorkflowsFromProxy(
|
||||
getWorkflowTemplates(
|
||||
clusterName: string | undefined,
|
||||
namespace: string,
|
||||
labels: string | undefined
|
||||
): Promise<IoArgoprojWorkflowV1alpha1WorkflowList>;
|
||||
): Promise<IoArgoprojWorkflowV1alpha1WorkflowTemplateList>;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import { Grid } from "@material-ui/core";
|
|||
import { OverviewTable } from "../WorkflowOverview/WorkflowOverview";
|
||||
import { useEntity } from "@backstage/plugin-catalog-react";
|
||||
import { isArgoWorkflowsAvailable } from "../../plugin";
|
||||
import { WorkflowTemplateTable } from "../WorkflowTemplateOverview/WorkflowTemplateOverview";
|
||||
|
||||
export const ArgoWorkflowsOverviewPage = () => (
|
||||
<Page themeId="tool">
|
||||
|
@ -40,3 +41,15 @@ export const ArgoWorkflowsOverviewCard = () => {
|
|||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const ArgoWorkflowsTemplatesOverviewCard = () => {
|
||||
const { entity } = useEntity();
|
||||
if (isArgoWorkflowsAvailable(entity)) {
|
||||
return (
|
||||
<InfoCard {...{ title: "Argo Workflows Templates" }}>
|
||||
<WorkflowTemplateTable />
|
||||
</InfoCard>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
export {
|
||||
ArgoWorkflowsOverviewPage,
|
||||
ArgoWorkflowsOverviewCard,
|
||||
ArgoWorkflowsTemplatesOverviewCard,
|
||||
} from "./Overview";
|
||||
|
|
|
@ -38,8 +38,7 @@ const mockKClient: jest.Mocked<KubernetesApi> = {
|
|||
const noopFetchApi = new MockFetchApi({ baseImplementation: "none" });
|
||||
const mockArgoWorkflows: jest.Mocked<ArgoWorkflowsApi> = {
|
||||
getWorkflows: jest.fn(),
|
||||
getWorkflowsFromK8s: jest.fn(),
|
||||
getWorkflowsFromProxy: jest.fn(),
|
||||
getWorkflowTemplates: jest.fn(),
|
||||
};
|
||||
|
||||
const apis: [AnyApiRef, Partial<unknown>][] = [
|
||||
|
|
|
@ -6,14 +6,10 @@ import React from "react";
|
|||
import Alert from "@material-ui/lab/Alert";
|
||||
import { useEntity } from "@backstage/plugin-catalog-react";
|
||||
import { IoArgoprojWorkflowV1alpha1WorkflowList } from "../../api/generated";
|
||||
import {
|
||||
ARGO_WORKFLOWS_LABEL_SELECTOR_ANNOTATION,
|
||||
CLUSTER_NAME_ANNOTATION,
|
||||
K8S_LABEL_SELECTOR_ANNOTATION,
|
||||
K8S_NAMESPACE_ANNOTATION,
|
||||
} from "../../plugin";
|
||||
import { getAnnotationValues, trimBaseUrl } from "../utils";
|
||||
|
||||
type TableData = {
|
||||
id: string;
|
||||
name: string;
|
||||
namespace: string;
|
||||
phase?: string;
|
||||
|
@ -26,24 +22,11 @@ export const OverviewTable = () => {
|
|||
const { entity } = useEntity();
|
||||
const apiClient = useApi(argoWorkflowsApiRef);
|
||||
const configApi = useApi(configApiRef);
|
||||
let argoWorkflowsBaseUrl = configApi.getOptionalString(
|
||||
"argoWorkflows.baseUrl"
|
||||
const argoWorkflowsBaseUrl = trimBaseUrl(
|
||||
configApi.getOptionalString("argoWorkflows.baseUrl")
|
||||
);
|
||||
if (argoWorkflowsBaseUrl && argoWorkflowsBaseUrl.endsWith("/")) {
|
||||
argoWorkflowsBaseUrl = argoWorkflowsBaseUrl.substring(
|
||||
0,
|
||||
argoWorkflowsBaseUrl.length - 1
|
||||
);
|
||||
}
|
||||
|
||||
const ln = entity.metadata.annotations?.[K8S_NAMESPACE_ANNOTATION];
|
||||
const ns = ln !== undefined ? ln : "default";
|
||||
const clusterName = entity.metadata.annotations?.[CLUSTER_NAME_ANNOTATION];
|
||||
const labelSelector =
|
||||
entity.metadata?.annotations?.[ARGO_WORKFLOWS_LABEL_SELECTOR_ANNOTATION] !==
|
||||
undefined
|
||||
? entity.metadata?.annotations?.[ARGO_WORKFLOWS_LABEL_SELECTOR_ANNOTATION]
|
||||
: entity.metadata.annotations?.[K8S_LABEL_SELECTOR_ANNOTATION];
|
||||
const { ns, clusterName, labelSelector } = getAnnotationValues(entity);
|
||||
|
||||
const columns: TableColumn[] = [
|
||||
{
|
||||
|
@ -99,11 +82,12 @@ export const OverviewTable = () => {
|
|||
if (loading) {
|
||||
return <Progress />;
|
||||
} else if (error) {
|
||||
return <Alert severity="error">{error.message}</Alert>;
|
||||
return <Alert severity="error">{`${error}`}</Alert>;
|
||||
}
|
||||
|
||||
const data = value?.items?.map((val) => {
|
||||
return {
|
||||
id: val.metadata.name,
|
||||
name: val.metadata.name,
|
||||
namespace: val.metadata.namespace,
|
||||
phase: val.status?.phase,
|
||||
|
@ -117,6 +101,7 @@ export const OverviewTable = () => {
|
|||
return (
|
||||
<Table
|
||||
options={{
|
||||
padding: "dense",
|
||||
paging: true,
|
||||
search: true,
|
||||
sorting: true,
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
import React from "react";
|
||||
import {
|
||||
MockConfigApi,
|
||||
MockFetchApi,
|
||||
renderInTestApp,
|
||||
TestApiProvider,
|
||||
} from "@backstage/test-utils";
|
||||
import {
|
||||
AnyApiRef,
|
||||
configApiRef,
|
||||
DiscoveryApi,
|
||||
discoveryApiRef,
|
||||
fetchApiRef,
|
||||
} from "@backstage/core-plugin-api";
|
||||
import { ArgoWorkflowsApi, argoWorkflowsApiRef } from "../../api";
|
||||
import { KubernetesApi, kubernetesApiRef } from "@backstage/plugin-kubernetes";
|
||||
import { EntityProvider } from "@backstage/plugin-catalog-react";
|
||||
import { WorkflowTemplateTable } from "./WorkflowTemplateOverview";
|
||||
import { simple } from "../../test-data/testResponseWorkflowTemplates";
|
||||
import { IoArgoprojWorkflowV1alpha1WorkflowTemplateList } from "../../api/generated";
|
||||
|
||||
const BASE_URL = "https://backstage.io";
|
||||
const mockConfigApi = new MockConfigApi({
|
||||
argoWorkflows: { baseUrl: BASE_URL },
|
||||
});
|
||||
const mockDiscoveryApi: jest.Mocked<DiscoveryApi> = {
|
||||
getBaseUrl: jest.fn().mockImplementation((id) => {
|
||||
return Promise.resolve(`https://backstage.io/${id}`);
|
||||
}),
|
||||
};
|
||||
const mockKClient: jest.Mocked<KubernetesApi> = {
|
||||
getObjectsByEntity: jest.fn(),
|
||||
getClusters: jest.fn(),
|
||||
getWorkloadsByEntity: jest.fn(),
|
||||
getCustomObjectsByEntity: jest.fn(),
|
||||
proxy: jest.fn(),
|
||||
};
|
||||
const noopFetchApi = new MockFetchApi({ baseImplementation: "none" });
|
||||
const mockArgoWorkflows: jest.Mocked<ArgoWorkflowsApi> = {
|
||||
getWorkflows: jest.fn(),
|
||||
getWorkflowTemplates: jest.fn(),
|
||||
};
|
||||
|
||||
const apis: [AnyApiRef, Partial<unknown>][] = [
|
||||
[discoveryApiRef, mockDiscoveryApi],
|
||||
[kubernetesApiRef, mockKClient],
|
||||
[configApiRef, mockConfigApi],
|
||||
[fetchApiRef, noopFetchApi],
|
||||
[argoWorkflowsApiRef, mockArgoWorkflows],
|
||||
];
|
||||
|
||||
const entity = {
|
||||
metadata: {
|
||||
namespace: "default",
|
||||
annotations: {
|
||||
"backstage.io/kubernetes-label-selector": "my=env",
|
||||
"backstage.io/kubernetes-namespace": "default",
|
||||
},
|
||||
name: "my-entity",
|
||||
},
|
||||
apiVersion: "backstage.io/v1alpha1",
|
||||
kind: "Component",
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe("WorkflowTemplateTable", () => {
|
||||
it("should display workflows without link", async () => {
|
||||
jest
|
||||
.spyOn(mockArgoWorkflows, "getWorkflowTemplates")
|
||||
.mockImplementation(
|
||||
(
|
||||
_n,
|
||||
_ns,
|
||||
_l
|
||||
): Promise<IoArgoprojWorkflowV1alpha1WorkflowTemplateList> => {
|
||||
return Promise.resolve(
|
||||
simple as unknown as IoArgoprojWorkflowV1alpha1WorkflowTemplateList
|
||||
);
|
||||
}
|
||||
);
|
||||
jest.spyOn(mockConfigApi, "getOptionalString").mockImplementation((_) => {
|
||||
return undefined;
|
||||
});
|
||||
const r = await renderInTestApp(
|
||||
<TestApiProvider apis={apis}>
|
||||
<EntityProvider entity={entity}>
|
||||
<WorkflowTemplateTable />
|
||||
</EntityProvider>
|
||||
</TestApiProvider>
|
||||
);
|
||||
const c = r.getByText(simple.items[0].metadata.name);
|
||||
expect(c).not.toHaveAttribute("href");
|
||||
});
|
||||
|
||||
it("should display workflows wth link", async () => {
|
||||
const spyWorkflows = jest
|
||||
.spyOn(mockArgoWorkflows, "getWorkflowTemplates")
|
||||
.mockImplementation(
|
||||
(
|
||||
_n,
|
||||
_ns,
|
||||
_l
|
||||
): Promise<IoArgoprojWorkflowV1alpha1WorkflowTemplateList> => {
|
||||
return Promise.resolve(
|
||||
simple as unknown as IoArgoprojWorkflowV1alpha1WorkflowTemplateList
|
||||
);
|
||||
}
|
||||
);
|
||||
const spyConfigApi = jest
|
||||
.spyOn(mockConfigApi, "getOptionalString")
|
||||
.mockImplementation((_n) => {
|
||||
return `https://backstage.io/`;
|
||||
});
|
||||
const r = await renderInTestApp(
|
||||
<TestApiProvider apis={apis}>
|
||||
<EntityProvider entity={entity}>
|
||||
<WorkflowTemplateTable data-testid="test" />
|
||||
</EntityProvider>
|
||||
</TestApiProvider>
|
||||
);
|
||||
expect(spyWorkflows).toHaveBeenCalledWith(undefined, "default", "my=env");
|
||||
expect(spyConfigApi).toHaveBeenCalledWith("argoWorkflows.baseUrl");
|
||||
const c = r.getByText(simple.items[0].metadata.name);
|
||||
expect(c).toHaveAttribute(
|
||||
"href",
|
||||
`${BASE_URL}/workflow-templates/default/${simple.items[0].metadata.name}`
|
||||
);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,82 @@
|
|||
import { useEntity } from "@backstage/plugin-catalog-react";
|
||||
import { configApiRef, useApi } from "@backstage/core-plugin-api";
|
||||
import { argoWorkflowsApiRef } from "../../api";
|
||||
import { getAnnotationValues, trimBaseUrl } from "../utils";
|
||||
import { Link, Progress, Table, TableColumn } from "@backstage/core-components";
|
||||
import React from "react";
|
||||
import useAsync from "react-use/lib/useAsync";
|
||||
import Alert from "@material-ui/lab/Alert";
|
||||
|
||||
type TableData = {
|
||||
id: string;
|
||||
name: string;
|
||||
namespace: string;
|
||||
entrypoint: string | undefined;
|
||||
};
|
||||
|
||||
export const WorkflowTemplateTable = () => {
|
||||
const { entity } = useEntity();
|
||||
const apiClient = useApi(argoWorkflowsApiRef);
|
||||
const configApi = useApi(configApiRef);
|
||||
const argoWorkflowsBaseUrl = trimBaseUrl(
|
||||
configApi.getOptionalString("argoWorkflows.baseUrl")
|
||||
);
|
||||
const { ns, clusterName, labelSelector } = getAnnotationValues(entity);
|
||||
|
||||
const columns: TableColumn[] = [
|
||||
{
|
||||
title: "Name",
|
||||
field: "name",
|
||||
render: (data: any | TableData, _): any => {
|
||||
if (data && argoWorkflowsBaseUrl) {
|
||||
return (
|
||||
<Link
|
||||
to={`${argoWorkflowsBaseUrl}/workflow-templates/${data.namespace}/${data.name}`}
|
||||
>
|
||||
{data.name}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
return data.name;
|
||||
},
|
||||
defaultSort: "desc",
|
||||
},
|
||||
{ title: "namespace", field: "namespace", type: "string" },
|
||||
{ title: "entrypoint", field: "entrypoint", type: "string" },
|
||||
];
|
||||
|
||||
const { value, loading, error } = useAsync(async () => {
|
||||
return await apiClient.getWorkflowTemplates(clusterName, ns, labelSelector);
|
||||
});
|
||||
|
||||
if (loading) {
|
||||
return <Progress />;
|
||||
} else if (error) {
|
||||
return <Alert severity="error">{`${error}`}</Alert>;
|
||||
}
|
||||
const data = value?.items?.map((val) => {
|
||||
return {
|
||||
id: val.metadata.name,
|
||||
name: val.metadata.name,
|
||||
namespace: val.metadata.namespace,
|
||||
entrypoint: val.spec.entrypoint,
|
||||
} as TableData;
|
||||
});
|
||||
if (data && data.length > 0) {
|
||||
return (
|
||||
<Table
|
||||
options={{
|
||||
padding: "dense",
|
||||
paging: true,
|
||||
search: true,
|
||||
sorting: true,
|
||||
}}
|
||||
columns={columns}
|
||||
data={data}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Alert severity="info">"No workflows found with provided labels"</Alert>
|
||||
);
|
||||
};
|
38
plugins/argo-workflows/src/components/utils.ts
Normal file
38
plugins/argo-workflows/src/components/utils.ts
Normal file
|
@ -0,0 +1,38 @@
|
|||
import { Entity } from "@backstage/catalog-model";
|
||||
import {
|
||||
ARGO_WORKFLOWS_LABEL_SELECTOR_ANNOTATION,
|
||||
CLUSTER_NAME_ANNOTATION,
|
||||
K8S_LABEL_SELECTOR_ANNOTATION,
|
||||
K8S_NAMESPACE_ANNOTATION,
|
||||
} from "../plugin";
|
||||
|
||||
export function trimBaseUrl(argoWorkflowsBaseUrl: string | undefined) {
|
||||
if (argoWorkflowsBaseUrl && argoWorkflowsBaseUrl.endsWith("/")) {
|
||||
return argoWorkflowsBaseUrl.substring(0, argoWorkflowsBaseUrl.length - 1);
|
||||
}
|
||||
return argoWorkflowsBaseUrl;
|
||||
}
|
||||
|
||||
export type getAnnotationValuesOutput = {
|
||||
ns: string;
|
||||
clusterName?: string;
|
||||
labelSelector?: string;
|
||||
};
|
||||
|
||||
export function getAnnotationValues(entity: Entity): getAnnotationValuesOutput {
|
||||
const ns =
|
||||
entity.metadata.annotations?.[K8S_NAMESPACE_ANNOTATION] !== undefined
|
||||
? entity.metadata.annotations?.[K8S_NAMESPACE_ANNOTATION]
|
||||
: "default";
|
||||
const clusterName = entity.metadata.annotations?.[CLUSTER_NAME_ANNOTATION];
|
||||
const labelSelector =
|
||||
entity.metadata?.annotations?.[ARGO_WORKFLOWS_LABEL_SELECTOR_ANNOTATION] !==
|
||||
undefined
|
||||
? entity.metadata?.annotations?.[ARGO_WORKFLOWS_LABEL_SELECTOR_ANNOTATION]
|
||||
: entity.metadata.annotations?.[K8S_LABEL_SELECTOR_ANNOTATION];
|
||||
return {
|
||||
ns: ns,
|
||||
clusterName: clusterName,
|
||||
labelSelector: labelSelector,
|
||||
};
|
||||
}
|
|
@ -2,5 +2,6 @@ export {
|
|||
argoWorkflowsPlugin,
|
||||
ArgoWorkflowsPage,
|
||||
EntityArgoWorkflowsOverviewCard,
|
||||
EntityArgoWorkflowsTemplateOverviewCard,
|
||||
isArgoWorkflowsAvailable,
|
||||
} from "./plugin";
|
||||
|
|
|
@ -54,6 +54,18 @@ export const EntityArgoWorkflowsOverviewCard = argoWorkflowsPlugin.provide(
|
|||
})
|
||||
);
|
||||
|
||||
export const EntityArgoWorkflowsTemplateOverviewCard =
|
||||
argoWorkflowsPlugin.provide(
|
||||
createRoutableExtension({
|
||||
name: "ArgoWorkflowsTemplatesOverviewCard",
|
||||
component: () =>
|
||||
import("./components/Overview").then(
|
||||
(m) => m.ArgoWorkflowsTemplatesOverviewCard
|
||||
),
|
||||
mountPoint: rootRouteRef,
|
||||
})
|
||||
);
|
||||
|
||||
export const isArgoWorkflowsAvailable = (entity: Entity) =>
|
||||
Boolean(
|
||||
entity?.metadata.annotations?.[ARGO_WORKFLOWS_LABEL_SELECTOR_ANNOTATION]
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
export const simple = {
|
||||
apiVersion: "v1",
|
||||
items: [
|
||||
{
|
||||
apiVersion: "argoproj.io/v1alpha1",
|
||||
kind: "WorkflowTemplate",
|
||||
metadata: {
|
||||
annotations: {
|
||||
"kubectl.kubernetes.io/last-applied-configuration":
|
||||
'{"apiVersion":"argoproj.io/v1alpha1","kind":"WorkflowTemplate","metadata":{"annotations":{},"name":"workflow-template-whalesay-template","namespace":"default"},"spec":{"entrypoint":"whalesay-template","templates":[{"inputs":{"parameters":[{"name":"message"}]},"name":"whalesay-template","steps":[[{"arguments":{"parameters":[{"name":"message","value":"{{inputs.parameters.message}}"}]},"name":"whalesay3","template":"whalesay-template-3"},{"name":"sleep","template":"sleep"}]]},{"container":{"args":["600"],"command":["sleep"],"image":"docker/whalesay"},"name":"sleep"},{"container":{"args":["{{inputs.parameters.message}}"],"command":["cowsay"],"image":"docker/whalesay"},"inputs":{"parameters":[{"name":"message"}]},"name":"whalesay-template-3"}],"ttlStrategy":{"secondsAfterCompletion":28800},"workflowMetadata":{"labels":{"env":"dev","my":"label"}}}}\n',
|
||||
},
|
||||
creationTimestamp: "2023-06-26T22:20:33Z",
|
||||
generation: 1,
|
||||
name: "workflow-template-whalesay-template",
|
||||
namespace: "default",
|
||||
resourceVersion: "76502835",
|
||||
uid: "c2ed5f0a-9093-4cb2-bac5-c9918bb3f8d7",
|
||||
},
|
||||
spec: {
|
||||
entrypoint: "whalesay-template",
|
||||
templates: [
|
||||
{
|
||||
inputs: {
|
||||
parameters: [
|
||||
{
|
||||
name: "message",
|
||||
},
|
||||
],
|
||||
},
|
||||
name: "whalesay-template",
|
||||
steps: [
|
||||
[
|
||||
{
|
||||
arguments: {
|
||||
parameters: [
|
||||
{
|
||||
name: "message",
|
||||
value: "{{inputs.parameters.message}}",
|
||||
},
|
||||
],
|
||||
},
|
||||
name: "whalesay3",
|
||||
template: "whalesay-template-3",
|
||||
},
|
||||
{
|
||||
name: "sleep",
|
||||
template: "sleep",
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
container: {
|
||||
args: ["600"],
|
||||
command: ["sleep"],
|
||||
image: "docker/whalesay",
|
||||
},
|
||||
name: "sleep",
|
||||
},
|
||||
{
|
||||
container: {
|
||||
args: ["{{inputs.parameters.message}}"],
|
||||
command: ["cowsay"],
|
||||
image: "docker/whalesay",
|
||||
},
|
||||
inputs: {
|
||||
parameters: [
|
||||
{
|
||||
name: "message",
|
||||
},
|
||||
],
|
||||
},
|
||||
name: "whalesay-template-3",
|
||||
},
|
||||
],
|
||||
ttlStrategy: {
|
||||
secondsAfterCompletion: 28800,
|
||||
},
|
||||
workflowMetadata: {
|
||||
labels: {
|
||||
env: "dev",
|
||||
my: "label",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
kind: "List",
|
||||
metadata: {
|
||||
resourceVersion: "",
|
||||
},
|
||||
};
|
Loading…
Reference in a new issue