diff --git a/plugins/argo-workflows/.eslintrc.js b/plugins/argo-workflows/.eslintrc.js
new file mode 100644
index 0000000..e2a53a6
--- /dev/null
+++ b/plugins/argo-workflows/.eslintrc.js
@@ -0,0 +1 @@
+module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
diff --git a/plugins/argo-workflows/README.md b/plugins/argo-workflows/README.md
new file mode 100644
index 0000000..e155d71
--- /dev/null
+++ b/plugins/argo-workflows/README.md
@@ -0,0 +1,13 @@
+# argo-workflows
+
+Welcome to the argo-workflows plugin!
+
+_This plugin was created through the Backstage CLI_
+
+## Getting started
+
+Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn start` in the root directory, and then navigating to [/argo-workflows](http://localhost:3000/argo-workflows).
+
+You can also serve the plugin in isolation by running `yarn start` in the plugin directory.
+This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads.
+It is only meant for local development, and the setup for it can be found inside the [/dev](./dev) directory.
diff --git a/plugins/argo-workflows/dev/index.tsx b/plugins/argo-workflows/dev/index.tsx
new file mode 100644
index 0000000..712176c
--- /dev/null
+++ b/plugins/argo-workflows/dev/index.tsx
@@ -0,0 +1,12 @@
+import React from 'react';
+import { createDevApp } from '@backstage/dev-utils';
+import { argoWorkflowsPlugin, ArgoWorkflowsPage } from '../src/plugin';
+
+createDevApp()
+ .registerPlugin(argoWorkflowsPlugin)
+ .addPage({
+ element: ,
+ title: 'Root Page',
+ path: '/argo-workflows'
+ })
+ .render();
diff --git a/plugins/argo-workflows/package.json b/plugins/argo-workflows/package.json
new file mode 100644
index 0000000..6383de5
--- /dev/null
+++ b/plugins/argo-workflows/package.json
@@ -0,0 +1,54 @@
+{
+ "name": "@internal/plugin-argo-workflows",
+ "version": "0.1.0",
+ "main": "src/index.ts",
+ "types": "src/index.ts",
+ "license": "Apache-2.0",
+ "private": true,
+ "publishConfig": {
+ "access": "public",
+ "main": "dist/index.esm.js",
+ "types": "dist/index.d.ts"
+ },
+ "backstage": {
+ "role": "frontend-plugin"
+ },
+ "scripts": {
+ "start": "backstage-cli package start",
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "clean": "backstage-cli package clean",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack"
+ },
+ "dependencies": {
+ "@backstage/core-components": "^0.13.1",
+ "@backstage/core-plugin-api": "^1.5.1",
+ "@backstage/plugin-catalog-react": "^1.7.0",
+ "@backstage/plugin-kubernetes": "^0.9.1",
+ "@backstage/theme": "^0.3.0",
+ "@material-ui/core": "^4.12.2",
+ "@material-ui/icons": "^4.9.1",
+ "@material-ui/lab": "4.0.0-alpha.61",
+ "react-use": "^17.2.4"
+ },
+ "peerDependencies": {
+ "react": "^16.13.1 || ^17.0.0"
+ },
+ "devDependencies": {
+ "@backstage/cli": "^0.22.7",
+ "@backstage/core-app-api": "^1.8.0",
+ "@backstage/dev-utils": "^1.0.15",
+ "@backstage/test-utils": "^1.3.1",
+ "@testing-library/jest-dom": "^5.10.1",
+ "@testing-library/react": "^12.1.3",
+ "@testing-library/user-event": "^14.0.0",
+ "@types/node": "*",
+ "cross-fetch": "^3.1.5",
+ "msw": "^1.0.0"
+ },
+ "files": [
+ "dist"
+ ]
+}
diff --git a/plugins/argo-workflows/src/api/indext.ts b/plugins/argo-workflows/src/api/indext.ts
new file mode 100644
index 0000000..a1e703d
--- /dev/null
+++ b/plugins/argo-workflows/src/api/indext.ts
@@ -0,0 +1,109 @@
+import {
+ ConfigApi,
+ createApiRef,
+ DiscoveryApi, OAuthRequestApi,
+} from '@backstage/core-plugin-api';
+
+import {KubernetesApi } from "@backstage/plugin-kubernetes";
+
+
+const API_VERSION = 'argoproj.io/v1alpha1'
+const WORKFLOW_PLURAL = 'workflows'
+export const argoWorkflowsApiRef = createApiRef({
+ id: 'plugin.argoworkflows',
+})
+export interface ArgoWorkflowsApi {
+ discoveryApi: DiscoveryApi
+ kubernetesApi: KubernetesApi
+ getWorkflows(clusterName: string | undefined, namespace: string | undefined, labels: string | undefined): Promise
+}
+
+type Metadata = {
+ annotations: Record
+ labels: Record
+ name: string
+ namespace: string
+}
+
+type Workflows = {
+ workflows: Workflow[]
+}
+
+
+
+export type Workflow = {
+ metadata: Metadata
+ spec: any
+ status?: any
+}
+
+type WorkflowStatus = {
+ finishedAt: string
+ startedAt: string
+ phase: string
+ progress: string
+
+}
+
+
+export class ArgoWorkflows implements ArgoWorkflowsApi {
+ discoveryApi: DiscoveryApi
+ kubernetesApi: KubernetesApi
+ configApi: ConfigApi
+ oauthRequestApi: OAuthRequestApi
+
+ constructor(discoveryApi: DiscoveryApi, kubernetesApi: KubernetesApi, configApi: ConfigApi, oauthRequestApi: OAuthRequestApi) {
+ this.discoveryApi = discoveryApi
+ this.kubernetesApi = kubernetesApi
+ this.configApi = configApi
+ this.oauthRequestApi = oauthRequestApi
+ }
+
+ async getWorkflows(clusterName: string | undefined, namespace: string | undefined, labels: string | undefined): Promise {
+ const ns = namespace !== undefined ? namespace : 'default'
+ const path = `/apis/${API_VERSION}/namespaces/${ns}/${WORKFLOW_PLURAL}`
+ const query = new URLSearchParams()
+ if (labels) {
+ query.set('labelSelector', labels)
+ }
+ const resp = await this.kubernetesApi.proxy({
+ clusterName: clusterName !== undefined ? clusterName: await this.getCluster(),
+ path: `${path}?${query.toString()}`
+ })
+
+ if (!resp.ok) {
+ return Promise.reject(`failed to fetch resources: ${resp.status}, ${resp.statusText}, ${await resp.json()}`)
+ }
+ return Promise.resolve(resp.json());
+ }
+
+ async getCluster(): Promise {
+ const clusters = await this.kubernetesApi.getClusters()
+ if (clusters.length > 0) {
+ return Promise.resolve(clusters[0].name)
+ }
+ return Promise.reject("no clusters found in configuration")
+ }
+
+ // async getToken(clusterName: string): Promise {
+ // const clusters = await this.kubernetesApi.getClusters()
+ // const cluster = clusters.find(c => {
+ // return c.name === clusterName
+ // })
+ // if (!cluster) {
+ // return Promise.reject(`cluster ${clusterName} not found`)
+ // }
+ // const oidc = OAuth2.create({
+ // discoveryApi: this.discoveryApi,
+ // oauthRequestApi: this.oauthRequestApi,
+ // provider: {
+ // id: cluster.oidcTokenProvider!,
+ // title: 'OIDC',
+ // icon: () => null,
+ // },
+ // environment: this.configApi.getOptionalString('auth.environment'),
+ // defaultScopes: ['openid', 'profile', 'email', 'groups'],
+ // })
+ // return oidc.getIdToken()
+ // }
+}
diff --git a/plugins/argo-workflows/src/components/Overview/Overview.tsx b/plugins/argo-workflows/src/components/Overview/Overview.tsx
new file mode 100644
index 0000000..6bc6e44
--- /dev/null
+++ b/plugins/argo-workflows/src/components/Overview/Overview.tsx
@@ -0,0 +1,24 @@
+
+import React from 'react';
+import {Header, HeaderLabel, Page, Content, ContentHeader, SupportButton} from "@backstage/core-components";
+import {Grid} from "@material-ui/core";
+import {VersionComponent} from "../Version/Version";
+
+
+export const OverviewComponent = () => (
+
+
+
+
+
+ Overview of your Argo Workflows
+
+
+
+
+
+
+
+)
diff --git a/plugins/argo-workflows/src/components/Overview/index.ts b/plugins/argo-workflows/src/components/Overview/index.ts
new file mode 100644
index 0000000..ff77359
--- /dev/null
+++ b/plugins/argo-workflows/src/components/Overview/index.ts
@@ -0,0 +1 @@
+export {OverviewComponent} from "./Overview";
diff --git a/plugins/argo-workflows/src/components/Version/Version.tsx b/plugins/argo-workflows/src/components/Version/Version.tsx
new file mode 100644
index 0000000..6c7bd51
--- /dev/null
+++ b/plugins/argo-workflows/src/components/Version/Version.tsx
@@ -0,0 +1,43 @@
+import {useApi} from "@backstage/core-plugin-api";
+import {argoWorkflowsApiRef} from "../../api/indext";
+import useAsync from "react-use/lib/useAsync";
+import {InfoCard, Progress, StructuredMetadataTable} from '@backstage/core-components'
+import React from "react";
+import Alert from "@material-ui/lab/Alert";
+import { useEntity } from '@backstage/plugin-catalog-react';
+
+
+
+export const VersionComponent = () => {
+ const {entity} = useEntity()
+ const apiClient = useApi(argoWorkflowsApiRef)
+
+ const ln = entity.metadata.annotations?.['backstage.io/kubernetes-namespace']
+ const ns = ln !== undefined ? ln : 'default'
+ const clusterName = entity.metadata.annotations?.['argo-workflows/cluster-name']
+
+ const k8sLabelSelector = entity.metadata.annotations?.['backstage.io/kubernetes-label-selector']
+
+ const {value, loading, error} = useAsync(
+ async (): Promise => {
+ return await apiClient.getWorkflows(clusterName, ns, k8sLabelSelector)
+ }
+ )
+ if (loading) {
+ return ;
+ } else if (error) {
+ return {error.message};
+ }
+ if (value) {
+ const m = {
+ namespaces: value
+ }
+ return (
+
+
+
+ )
+ }
+ return Oh no
+
+}
diff --git a/plugins/argo-workflows/src/index.ts b/plugins/argo-workflows/src/index.ts
new file mode 100644
index 0000000..5b080f4
--- /dev/null
+++ b/plugins/argo-workflows/src/index.ts
@@ -0,0 +1 @@
+export { argoWorkflowsPlugin, ArgoWorkflowsPage } from './plugin';
diff --git a/plugins/argo-workflows/src/plugin.test.ts b/plugins/argo-workflows/src/plugin.test.ts
new file mode 100644
index 0000000..bcb714a
--- /dev/null
+++ b/plugins/argo-workflows/src/plugin.test.ts
@@ -0,0 +1,7 @@
+import { argoWorkflowsPlugin } from './plugin';
+
+describe('argo-workflows', () => {
+ it('should export plugin', () => {
+ expect(argoWorkflowsPlugin).toBeDefined();
+ });
+});
diff --git a/plugins/argo-workflows/src/plugin.ts b/plugins/argo-workflows/src/plugin.ts
new file mode 100644
index 0000000..51a2b55
--- /dev/null
+++ b/plugins/argo-workflows/src/plugin.ts
@@ -0,0 +1,42 @@
+import {
+ configApiRef,
+ createApiFactory,
+ createPlugin,
+ createRoutableExtension,
+ discoveryApiRef, oauthRequestApiRef
+} from '@backstage/core-plugin-api';
+
+import { rootRouteRef } from './routes';
+import {ArgoWorkflows, argoWorkflowsApiRef} from "./api/indext";
+import {kubernetesApiRef} from "@backstage/plugin-kubernetes";
+
+
+export const argoWorkflowsPlugin = createPlugin({
+ id: 'argo-workflows',
+ routes: {
+ root: rootRouteRef,
+ },
+ apis: [
+ createApiFactory({
+ api: argoWorkflowsApiRef,
+ deps: {
+ discoveryApi: discoveryApiRef,
+ kubernetesApi: kubernetesApiRef,
+ oauthRequestApi: oauthRequestApiRef,
+ configApi: configApiRef},
+ factory: ({
+ discoveryApi, kubernetesApi, configApi, oauthRequestApi,
+ }) =>
+ new ArgoWorkflows(discoveryApi, kubernetesApi, configApi, oauthRequestApi)
+ })
+ ]
+});
+
+export const ArgoWorkflowsPage = argoWorkflowsPlugin.provide(
+ createRoutableExtension({
+ name: 'ArgoWorkflowsPage',
+ component: () =>
+ import('./components/Overview').then(m => m.OverviewComponent),
+ mountPoint: rootRouteRef,
+ }),
+);
diff --git a/plugins/argo-workflows/src/routes.ts b/plugins/argo-workflows/src/routes.ts
new file mode 100644
index 0000000..f971bdd
--- /dev/null
+++ b/plugins/argo-workflows/src/routes.ts
@@ -0,0 +1,5 @@
+import { createRouteRef } from '@backstage/core-plugin-api';
+
+export const rootRouteRef = createRouteRef({
+ id: 'argo-workflows',
+});
diff --git a/plugins/argo-workflows/src/setupTests.ts b/plugins/argo-workflows/src/setupTests.ts
new file mode 100644
index 0000000..48c09b5
--- /dev/null
+++ b/plugins/argo-workflows/src/setupTests.ts
@@ -0,0 +1,2 @@
+import '@testing-library/jest-dom';
+import 'cross-fetch/polyfill';