start adding tests
This commit is contained in:
parent
cf2bdf9d9b
commit
afc86729c3
4 changed files with 440 additions and 23 deletions
103
plugins/argo-workflows/src/api/ArgoWorkflows.test.tsx
Normal file
103
plugins/argo-workflows/src/api/ArgoWorkflows.test.tsx
Normal file
|
@ -0,0 +1,103 @@
|
|||
import {DiscoveryApi} from "@backstage/core-plugin-api";
|
||||
import {ArgoWorkflows} from "./ArgoWorkflows";
|
||||
import {KubernetesApi} from "@backstage/plugin-kubernetes";
|
||||
import {MockConfigApi, MockFetchApi} from "@backstage/test-utils";
|
||||
import {FrontendHostDiscovery} from "@backstage/core-app-api";
|
||||
import {UserIdentity} from "@backstage/core-components";
|
||||
import {inProgress} from "../test-data/in-progress";
|
||||
|
||||
|
||||
describe('ArgoWorkflowsClient', () => {
|
||||
const mockDiscoveryApi: jest.Mocked<DiscoveryApi> = {
|
||||
getBaseUrl: jest.fn().mockImplementation((id) => {
|
||||
return Promise.resolve(`https://backstage.io/${id}`)
|
||||
})
|
||||
}
|
||||
const mockConfigApi = new MockConfigApi({
|
||||
app: { baseUrl: 'https://backstage.io'}
|
||||
})
|
||||
const noopFetchApi = new MockFetchApi({baseImplementation: 'none'})
|
||||
|
||||
const mockKClient: jest.Mocked<KubernetesApi> = {
|
||||
getObjectsByEntity: jest.fn(),
|
||||
getClusters: jest.fn(),
|
||||
getWorkloadsByEntity: jest.fn(),
|
||||
getCustomObjectsByEntity: jest.fn(),
|
||||
proxy: jest.fn()
|
||||
}
|
||||
|
||||
|
||||
beforeAll( () => {
|
||||
jest.spyOn(FrontendHostDiscovery.prototype, 'getBaseUrl')
|
||||
.mockImplementation((id) => {
|
||||
return Promise.resolve(`https://backstage.io/${id}`)
|
||||
})
|
||||
jest.spyOn(UserIdentity.prototype, 'getCredentials')
|
||||
.mockImplementation( () => {
|
||||
return Promise.resolve({token: 'abc'})
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('can fetch from k8s', async () => {
|
||||
mockKClient.proxy.mockResolvedValue(
|
||||
{
|
||||
status: 200,
|
||||
ok: true,
|
||||
text: async () => (JSON.stringify(inProgress))
|
||||
} as Response
|
||||
)
|
||||
|
||||
const a = new ArgoWorkflows(mockDiscoveryApi, mockKClient, mockConfigApi, noopFetchApi)
|
||||
const spy = jest.spyOn(mockKClient, "proxy")
|
||||
const resp = await a.getWorkflowsFromK8s("abc", "default", "my=env")
|
||||
expect(resp.items.length).toBe(1)
|
||||
expect(spy).toHaveBeenCalledWith({
|
||||
clusterName: 'abc',
|
||||
path: "/apis/argoproj.io/v1alpha1/namespaces/default/workflows?timeoutSeconds=30&labelSelector=my%3Denv",
|
||||
})
|
||||
})
|
||||
it('can fetch from default k8s cluster', async () => {
|
||||
mockKClient.proxy.mockResolvedValue(
|
||||
{
|
||||
status: 200,
|
||||
ok: true,
|
||||
text: async () => (JSON.stringify(inProgress))
|
||||
} as Response
|
||||
)
|
||||
mockKClient.getClusters.mockResolvedValue(
|
||||
[
|
||||
{
|
||||
name: 'cluster-1',
|
||||
authProvider: 'provider-1'
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
const a = new ArgoWorkflows(mockDiscoveryApi, mockKClient, mockConfigApi, noopFetchApi)
|
||||
const spy = jest.spyOn(a, "getCluster")
|
||||
const resp = await a.getWorkflowsFromK8s(undefined, "default", "my=env")
|
||||
expect(resp.items.length).toBe(1)
|
||||
expect(spy).toHaveBeenCalled()
|
||||
})
|
||||
it('non ok status returned', async () => {
|
||||
mockKClient.proxy.mockResolvedValue(
|
||||
{
|
||||
status: 500,
|
||||
ok: false,
|
||||
statusText: "something went wrong",
|
||||
text: async () => ("oh no")
|
||||
} as Response
|
||||
)
|
||||
|
||||
const a = new ArgoWorkflows(mockDiscoveryApi, mockKClient, mockConfigApi, noopFetchApi)
|
||||
await expect(a.getWorkflowsFromK8s("abc", "default", 'not used'))
|
||||
.rejects.toEqual("failed to fetch resources: 500, something went wrong, oh no")
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import {ConfigApi, DiscoveryApi, IdentityApi} from "@backstage/core-plugin-api";
|
||||
import {ConfigApi, DiscoveryApi, FetchApi} from "@backstage/core-plugin-api";
|
||||
import {KubernetesApi} from "@backstage/plugin-kubernetes";
|
||||
import {IoArgoprojWorkflowV1alpha1WorkflowList} from "./generated";
|
||||
import {ArgoWorkflowsApi} from "./index";
|
||||
|
@ -14,13 +14,13 @@ export class ArgoWorkflows implements ArgoWorkflowsApi {
|
|||
discoveryApi: DiscoveryApi
|
||||
kubernetesApi: KubernetesApi
|
||||
configApi: ConfigApi
|
||||
identityApi: IdentityApi
|
||||
fetchApi: FetchApi
|
||||
|
||||
constructor(discoveryApi: DiscoveryApi, kubernetesApi: KubernetesApi, configApi: ConfigApi, identityApi: IdentityApi) {
|
||||
constructor(discoveryApi: DiscoveryApi, kubernetesApi: KubernetesApi, configApi: ConfigApi, fetchApi: FetchApi) {
|
||||
this.discoveryApi = discoveryApi
|
||||
this.kubernetesApi = kubernetesApi
|
||||
this.configApi = configApi
|
||||
this.identityApi = identityApi
|
||||
this.fetchApi = fetchApi
|
||||
}
|
||||
|
||||
async getWorkflowsFromK8s(clusterName: string | undefined, namespace: string | undefined, labels: string | undefined): Promise<IoArgoprojWorkflowV1alpha1WorkflowList> {
|
||||
|
@ -39,7 +39,7 @@ export class ArgoWorkflows implements ArgoWorkflowsApi {
|
|||
})
|
||||
|
||||
if (!resp.ok) {
|
||||
return Promise.reject(`failed to fetch resources: ${resp.status}, ${resp.statusText}, ${await resp.json()}`)
|
||||
return Promise.reject(`failed to fetch resources: ${resp.status}, ${resp.statusText}, ${await resp.text()}`)
|
||||
}
|
||||
// need validation
|
||||
return JSON.parse(await resp.text()) as IoArgoprojWorkflowV1alpha1WorkflowList
|
||||
|
@ -64,19 +64,7 @@ export class ArgoWorkflows implements ArgoWorkflowsApi {
|
|||
if (labels) {
|
||||
query.set(API_LABEL_SELECTOR, labels)
|
||||
}
|
||||
|
||||
const { token } = await this.identityApi.getCredentials()
|
||||
|
||||
const headers = new Headers(
|
||||
{
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${token}`,
|
||||
}
|
||||
)
|
||||
|
||||
const resp = await fetch(`${url}?${query.toString()}`, {
|
||||
headers: headers
|
||||
})
|
||||
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.json()}`)
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
createApiFactory,
|
||||
createPlugin,
|
||||
createRoutableExtension,
|
||||
discoveryApiRef, identityApiRef
|
||||
discoveryApiRef, fetchApiRef
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
import { rootRouteRef } from './routes';
|
||||
|
@ -22,12 +22,13 @@ export const argoWorkflowsPlugin = createPlugin({
|
|||
deps: {
|
||||
discoveryApi: discoveryApiRef,
|
||||
kubernetesApi: kubernetesApiRef,
|
||||
identityApi: identityApiRef,
|
||||
configApi: configApiRef},
|
||||
configApi: configApiRef,
|
||||
fetchApi: fetchApiRef,
|
||||
},
|
||||
factory: ({
|
||||
discoveryApi, kubernetesApi, configApi, identityApi,
|
||||
discoveryApi, kubernetesApi, configApi, fetchApi,
|
||||
}) =>
|
||||
new ArgoWorkflows(discoveryApi, kubernetesApi, configApi, identityApi)
|
||||
new ArgoWorkflows(discoveryApi, kubernetesApi, configApi, fetchApi)
|
||||
})
|
||||
]
|
||||
});
|
||||
|
|
325
plugins/argo-workflows/src/test-data/in-progress.ts
Normal file
325
plugins/argo-workflows/src/test-data/in-progress.ts
Normal file
|
@ -0,0 +1,325 @@
|
|||
|
||||
export const inProgress= {
|
||||
"apiVersion": "v1",
|
||||
"items": [
|
||||
{
|
||||
"apiVersion": "argoproj.io/v1alpha1",
|
||||
"kind": "Workflow",
|
||||
"metadata": {
|
||||
"annotations": {
|
||||
"workflows.argoproj.io/pod-name-format": "v2"
|
||||
},
|
||||
"creationTimestamp": "2023-06-27T21:41:33Z",
|
||||
"generateName": "test-workflow-",
|
||||
"generation": 3,
|
||||
"labels": {
|
||||
"backstage.io/kubernetes-id": "backstage",
|
||||
"env": "dev",
|
||||
"my": "label",
|
||||
"workflows.argoproj.io/phase": "Running"
|
||||
},
|
||||
"name": "test-workflow-f49nr",
|
||||
"namespace": "default",
|
||||
"resourceVersion": "44977391",
|
||||
"uid": "188b33ab-c877-4e04-901c-32babece9573"
|
||||
},
|
||||
"spec": {
|
||||
"arguments": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "message",
|
||||
"value": "from workflow"
|
||||
}
|
||||
]
|
||||
},
|
||||
"workflowTemplateRef": {
|
||||
"name": "workflow-template-whalesay-template"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"artifactGCStatus": {
|
||||
"notSpecified": true
|
||||
},
|
||||
"artifactRepositoryRef": {
|
||||
"artifactRepository": {},
|
||||
"default": true
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"status": "True",
|
||||
"type": "PodRunning"
|
||||
}
|
||||
],
|
||||
"finishedAt": null,
|
||||
"nodes": {
|
||||
"test-workflow-f49nr": {
|
||||
"children": [
|
||||
"test-workflow-f49nr-1432144569"
|
||||
],
|
||||
"displayName": "test-workflow-f49nr",
|
||||
"finishedAt": null,
|
||||
"id": "test-workflow-f49nr",
|
||||
"inputs": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "message",
|
||||
"value": "from workflow"
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": "test-workflow-f49nr",
|
||||
"phase": "Running",
|
||||
"progress": "1/2",
|
||||
"startedAt": "2023-06-27T21:41:33Z",
|
||||
"templateName": "whalesay-template",
|
||||
"templateScope": "local/",
|
||||
"type": "Steps"
|
||||
},
|
||||
"test-workflow-f49nr-1432144569": {
|
||||
"boundaryID": "test-workflow-f49nr",
|
||||
"children": [
|
||||
"test-workflow-f49nr-1588075630",
|
||||
"test-workflow-f49nr-2771663768"
|
||||
],
|
||||
"displayName": "[0]",
|
||||
"finishedAt": null,
|
||||
"id": "test-workflow-f49nr-1432144569",
|
||||
"name": "test-workflow-f49nr[0]",
|
||||
"phase": "Running",
|
||||
"progress": "1/2",
|
||||
"startedAt": "2023-06-27T21:41:33Z",
|
||||
"templateScope": "local/",
|
||||
"type": "StepGroup"
|
||||
},
|
||||
"test-workflow-f49nr-1588075630": {
|
||||
"boundaryID": "test-workflow-f49nr",
|
||||
"displayName": "whalesay3",
|
||||
"finishedAt": "2023-06-27T21:41:37Z",
|
||||
"hostNodeName": "ip-192-168-10-135.us-west-2.compute.internal",
|
||||
"id": "test-workflow-f49nr-1588075630",
|
||||
"inputs": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "message",
|
||||
"value": "from workflow"
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": "test-workflow-f49nr[0].whalesay3",
|
||||
"outputs": {
|
||||
"exitCode": "0"
|
||||
},
|
||||
"phase": "Succeeded",
|
||||
"progress": "1/1",
|
||||
"resourcesDuration": {
|
||||
"cpu": 4,
|
||||
"memory": 4
|
||||
},
|
||||
"startedAt": "2023-06-27T21:41:33Z",
|
||||
"templateName": "whalesay-template-3",
|
||||
"templateScope": "local/",
|
||||
"type": "Pod"
|
||||
},
|
||||
"test-workflow-f49nr-2771663768": {
|
||||
"boundaryID": "test-workflow-f49nr",
|
||||
"displayName": "sleep",
|
||||
"finishedAt": null,
|
||||
"hostNodeName": "ip-192-168-5-156.us-west-2.compute.internal",
|
||||
"id": "test-workflow-f49nr-2771663768",
|
||||
"name": "test-workflow-f49nr[0].sleep",
|
||||
"phase": "Running",
|
||||
"progress": "0/1",
|
||||
"startedAt": "2023-06-27T21:41:33Z",
|
||||
"templateName": "sleep",
|
||||
"templateScope": "local/",
|
||||
"type": "Pod"
|
||||
}
|
||||
},
|
||||
"phase": "Running",
|
||||
"progress": "1/2",
|
||||
"resourcesDuration": {
|
||||
"cpu": 4,
|
||||
"memory": 4
|
||||
},
|
||||
"startedAt": "2023-06-27T21:41:33Z",
|
||||
"storedTemplates": {
|
||||
"namespaced/workflow-template-whalesay-template/sleep": {
|
||||
"container": {
|
||||
"args": [
|
||||
"600"
|
||||
],
|
||||
"command": [
|
||||
"sleep"
|
||||
],
|
||||
"image": "docker/whalesay",
|
||||
"name": "",
|
||||
"resources": {}
|
||||
},
|
||||
"inputs": {},
|
||||
"metadata": {},
|
||||
"name": "sleep",
|
||||
"outputs": {}
|
||||
},
|
||||
"namespaced/workflow-template-whalesay-template/whalesay-template": {
|
||||
"inputs": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "message"
|
||||
}
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"name": "whalesay-template",
|
||||
"outputs": {},
|
||||
"steps": [
|
||||
[
|
||||
{
|
||||
"arguments": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "message",
|
||||
"value": "{{inputs.parameters.message}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": "whalesay3",
|
||||
"template": "whalesay-template-3"
|
||||
},
|
||||
{
|
||||
"arguments": {},
|
||||
"name": "sleep",
|
||||
"template": "sleep"
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"namespaced/workflow-template-whalesay-template/whalesay-template-3": {
|
||||
"container": {
|
||||
"args": [
|
||||
"{{inputs.parameters.message}}"
|
||||
],
|
||||
"command": [
|
||||
"cowsay"
|
||||
],
|
||||
"image": "docker/whalesay",
|
||||
"name": "",
|
||||
"resources": {}
|
||||
},
|
||||
"inputs": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "message"
|
||||
}
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"name": "whalesay-template-3",
|
||||
"outputs": {}
|
||||
}
|
||||
},
|
||||
"storedWorkflowTemplateSpec": {
|
||||
"arguments": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "message",
|
||||
"value": "from workflow"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entrypoint": "whalesay-template",
|
||||
"templates": [
|
||||
{
|
||||
"inputs": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "message"
|
||||
}
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"name": "whalesay-template",
|
||||
"outputs": {},
|
||||
"steps": [
|
||||
[
|
||||
{
|
||||
"arguments": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "message",
|
||||
"value": "{{inputs.parameters.message}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": "whalesay3",
|
||||
"template": "whalesay-template-3"
|
||||
},
|
||||
{
|
||||
"arguments": {},
|
||||
"name": "sleep",
|
||||
"template": "sleep"
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"container": {
|
||||
"args": [
|
||||
"600"
|
||||
],
|
||||
"command": [
|
||||
"sleep"
|
||||
],
|
||||
"image": "docker/whalesay",
|
||||
"name": "",
|
||||
"resources": {}
|
||||
},
|
||||
"inputs": {},
|
||||
"metadata": {},
|
||||
"name": "sleep",
|
||||
"outputs": {}
|
||||
},
|
||||
{
|
||||
"container": {
|
||||
"args": [
|
||||
"{{inputs.parameters.message}}"
|
||||
],
|
||||
"command": [
|
||||
"cowsay"
|
||||
],
|
||||
"image": "docker/whalesay",
|
||||
"name": "",
|
||||
"resources": {}
|
||||
},
|
||||
"inputs": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "message"
|
||||
}
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"name": "whalesay-template-3",
|
||||
"outputs": {}
|
||||
}
|
||||
],
|
||||
"ttlStrategy": {
|
||||
"secondsAfterCompletion": 28800
|
||||
},
|
||||
"workflowMetadata": {
|
||||
"labels": {
|
||||
"env": "dev",
|
||||
"my": "label"
|
||||
}
|
||||
},
|
||||
"workflowTemplateRef": {
|
||||
"name": "workflow-template-whalesay-template"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"kind": "List",
|
||||
"metadata": {
|
||||
"resourceVersion": ""
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue