Skip to content

Commit

Permalink
feat(orchestrator): handle assessment workflow and make optional the …
Browse files Browse the repository at this point in the history
…workflowsSource config (#35)

* feat: issue FLPATH-591 - Add assessment workflow type and display outputs (#21)

* Configure for assessment swf

* filter assessment on workflow definition page

* workflow columns

* workflow columns

* workflow columns

* workflow filter

* feat: Render assessment results supporting dynamic categories

* issue FLPATH-657: workflow label

* Revert "Configure for assessment swf"

This reverts commit b4048e1.

* Revert sonata service port

* Add key for workflow options category

* Fix workflow execution from choose btn

* Fix review comments

* address comments

* Fix review comment to switch to useRouteRef

* fix review comments

* fix review comments

---------

Co-authored-by: richardwang98 <[email protected]>

* feat: make optional the workflowsSource config (#25)

---------

Co-authored-by: anludke <[email protected]>
  • Loading branch information
2 people authored and caponetto committed Dec 26, 2023
1 parent d8d53fa commit 677e66c
Show file tree
Hide file tree
Showing 13 changed files with 234 additions and 22 deletions.
2 changes: 1 addition & 1 deletion plugins/orchestrator-backend/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface Config {
/**
* Workflows definitions source configurations
*/
workflowsSource:
workflowsSource?:
| {
/**
* Remote git repository where workflows definitions are stored
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';
import { Logger } from 'winston';

import {
ASSESSMENT_WORKFLOW_TYPE,
default_catalog_environment,
default_catalog_owner,
orchestrator_service_ready_topic,
workflow_type,
WorkflowCategory,
WorkflowItem,
} from '@janus-idp/backstage-plugin-orchestrator-common';

Expand Down Expand Up @@ -154,14 +156,19 @@ export class OrchestratorEntityProvider
): TemplateEntityV1beta3[] {
return items.map(i => {
const sanitizedId = i.definition.id.replace(/ /g, '_');
const category: WorkflowCategory = i.definition.annotations?.find(
annotation => annotation === ASSESSMENT_WORKFLOW_TYPE,
)
? WorkflowCategory.ASSESSMENT
: WorkflowCategory.INFRASTRUCTURE;
return {
apiVersion: 'scaffolder.backstage.io/v1beta3',
kind: 'Template',
metadata: {
name: sanitizedId,
title: i.definition.name,
description: i.definition.description,
tags: [workflow_type],
tags: [category],
annotations: {
[ANNOTATION_LOCATION]: `url:${this.sonataFlowServiceUrl}`,
[ANNOTATION_ORIGIN_LOCATION]: `url:${this.sonataFlowServiceUrl}`,
Expand Down
13 changes: 9 additions & 4 deletions plugins/orchestrator-backend/src/service/SonataFlowService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ export class SonataFlowService {
this.connection = this.extractConnectionConfig(config);
}

public get autoStart(): boolean {
return this.connection.autoStart;
}

public get url(): string {
if (!this.connection.port) {
return this.connection.host;
Expand Down Expand Up @@ -187,7 +191,7 @@ export class SonataFlowService {

public async fetchProcessInstances(): Promise<ProcessInstance[] | undefined> {
const graphQlQuery =
'{ ProcessInstances (where: {processId: {isNull: false} } ) { id, processName, processId, state, start, lastUpdate, end, nodes { id }, variables, parentProcessInstance {id, processName, businessKey} } }';
'{ ProcessInstances ( orderBy: { start: ASC }, where: {processId: {isNull: false} } ) { id, processName, processId, state, start, lastUpdate, end, nodes { id }, variables, parentProcessInstance {id, processName, businessKey} } }';

try {
const response = await executeWithRetry(() =>
Expand Down Expand Up @@ -371,9 +375,10 @@ export class SonataFlowService {
'orchestrator.sonataFlowService.port',
);

const resourcesPath = config.getString(
'orchestrator.sonataFlowService.workflowsSource.localPath',
);
const resourcesPath =
config.getOptionalString(
'orchestrator.sonataFlowService.workflowsSource.localPath',
) ?? '';

const containerImage =
config.getOptionalString('orchestrator.sonataFlowService.container') ??
Expand Down
7 changes: 4 additions & 3 deletions plugins/orchestrator-backend/src/service/WorkflowService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ export class WorkflowService {
this.sonataFlowService = sonataFlowService;
this.logger = logger;
this.githubService = new GitService(logger, config);
this.repoURL = config.getString(
'orchestrator.sonataFlowService.workflowsSource.gitRepositoryUrl',
);
this.repoURL =
config.getOptionalString(
'orchestrator.sonataFlowService.workflowsSource.gitRepositoryUrl',
) ?? '';
this.autoPush =
config.getOptionalBoolean(
'orchestrator.sonataFlowService.workflowsSource.autoPush',
Expand Down
5 changes: 4 additions & 1 deletion plugins/orchestrator-common/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,11 @@ export const workflow_yaml_sample: WorkflowSample = {
export const default_sonataflow_container_image =
'quay.io/kiegroup/kogito-swf-devmode-nightly:main-2023-08-30';
export const default_sonataflow_persistance_path = '/home/kogito/persistence';
export const default_catalog_owner = 'infrastructure';
export const default_catalog_owner = 'orchestrator';
export const default_catalog_environment = 'development';
export const default_editor_path = 'https://start.kubesmarts.org';

export const default_workflows_path = 'workflows';

export const ASSESSMENT_WORKFLOW_TYPE = 'workflow-type/assessment';
export const INFRASTRUCTURE_WORKFLOW_TYPE = 'workflow-type/infrastructure';
5 changes: 5 additions & 0 deletions plugins/orchestrator-common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,8 @@ export interface WorkflowDataInputSchemaResponse {
export interface WorkflowExecutionResponse {
id: string;
}

export enum WorkflowCategory {
ASSESSMENT = 'assessment',
INFRASTRUCTURE = 'infrastructure',
}
3 changes: 3 additions & 0 deletions plugins/orchestrator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,15 @@ orchestrator:
sonataFlowService:
baseUrl: http://localhost
port: 8899
autoStart: true
workflowsSource:
gitRepositoryUrl: https://github.com/tiagodolphine/backstage-orchestrator-workflows
localPath: /tmp/orchestrator/repository
autoPush: true
```
when interacting with an existing Sonataflow backend service from `baseUrl` and `port`, `autoStart` needs to be unset or set to `false`, also the section of `workflowSource` can be neglect.

For more information about the configuration options, including other optional properties, see the [config.d.ts](../orchestrator-common/config.d.ts) file.

- Although optional, you may also want to set up the `GITHUB_TOKEN` environment variable to allow the Orchestrator to access the GitHub API.
Expand Down
1 change: 1 addition & 0 deletions plugins/orchestrator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"json-schema": "^0.4.0",
"react-hook-form": "^7.45.1",
"react-json-view": "^1.21.3",
"moment": "^2.29.4",
"react-moment": "^1.1.3",
"react-use": "^17.4.0",
"vscode-languageserver-types": "^3.16.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { orchestratorApiRef } from '../../api';
import { newWorkflowRef, workflowInstancesRouteRef } from '../../routes';
import { BaseOrchestratorPage } from '../BaseOrchestratorPage/BaseOrchestratorPage';
import { OrchestratorSupportButton } from '../OrchestratorSupportButton/OrchestratorSupportButton';
import { WorkflowsTable } from '../WorkflowDefinitionsListComponent/WorkflowDefinitionsListComponent';
import { WorkflowsTable } from '../WorkflowDefinitionsListComponent';

export const OrchestratorPage = () => {
const orchestratorApi = useApi(orchestratorApiRef);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const OrchestratorScaffolderTemplateCard = (

const onSelectedExtended = useCallback(
(template: TemplateEntityV1beta3) => {
const isWorkflow = template.metadata.tags?.includes(workflow_type);
const isWorkflow = template.spec.type === workflow_type;

if (!isWorkflow) {
onSelected?.(template);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback } from 'react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';

import { Table, TableColumn } from '@backstage/core-components';
Expand All @@ -8,9 +8,12 @@ import DeleteForever from '@material-ui/icons/DeleteForever';
import Edit from '@material-ui/icons/Edit';
import Pageview from '@material-ui/icons/Pageview';
import PlayArrow from '@material-ui/icons/PlayArrow';
import moment from 'moment';

import {
ASSESSMENT_WORKFLOW_TYPE,
extractWorkflowFormatFromUri,
WorkflowCategory,
WorkflowItem,
} from '@janus-idp/backstage-plugin-orchestrator-common';

Expand All @@ -27,26 +30,93 @@ type WorkflowsTableProps = {

export const WorkflowsTable = ({ items }: WorkflowsTableProps) => {
const orchestratorApi = useApi(orchestratorApiRef);

const navigate = useNavigate();
const definitionLink = useRouteRef(workflowDefinitionsRouteRef);
const executeWorkflowLink = useRouteRef(executeWorkflowRouteRef);
const editLink = useRouteRef(editWorkflowRouteRef);
const [data, setData] = useState<Row[]>([]);

interface Row {
id: string;
name: string;
lastRun: string;
lastRunStatus: string;
type: WorkflowCategory;
components: string;
format: string;
}

const columns: TableColumn[] = [{ title: 'Name', field: 'name' }];
const data: Row[] = items.map(item => {
const columns: TableColumn[] = [
{ title: 'Name', field: 'name' },
{ title: 'Last run', field: 'lastRun' },
{ title: 'Last run status', field: 'lastRunStatus' },
{ title: 'Type', field: 'type' },
{ title: 'Components', field: 'components' },
];

const initTableState = useMemo(() => {
const assessmentExist = !!items.find(
item =>
item.definition.annotations?.find(
annotation => annotation === ASSESSMENT_WORKFLOW_TYPE,
),
);
return {
id: item.definition.id,
name: item.definition.name ?? '',
format: extractWorkflowFormatFromUri(item.uri),
filtersOpen: true,
filters: assessmentExist
? { Type: WorkflowCategory.ASSESSMENT }
: undefined,
};
});
}, [items]);

const getInitialState = useMemo(() => {
return items.map(item => {
return {
id: item.definition.id,
name: item.definition.name ?? '',
lastRun: '',
lastRunStatus: '',
type: item.definition.annotations?.find(
annotation => annotation === ASSESSMENT_WORKFLOW_TYPE,
)
? WorkflowCategory.ASSESSMENT
: WorkflowCategory.INFRASTRUCTURE,
components: '---',
format: extractWorkflowFormatFromUri(item.uri),
};
});
}, [items]);

const loadFromInstances = useCallback(
(initData: Row[]) => {
orchestratorApi.getInstances().then(instances => {
const clonedData: Row[] = [];
for (const init_row of initData) {
const row = { ...init_row };
const instancesById = instances.filter(
instance => instance.processId === row.id,
);
const lastRunInstance = instancesById.at(-1);
if (lastRunInstance) {
row.lastRun = moment(lastRunInstance.start?.toString()).format(
'MMMM DD, YYYY',
);
row.lastRunStatus = lastRunInstance.state;
row.components = instancesById.length.toString();
}
clonedData.push(row);
}
setData(clonedData);
});
},
[orchestratorApi],
);

useEffect(() => {
const initData = getInitialState;
setData(initData);
loadFromInstances(initData);
}, [getInitialState, loadFromInstances]);

const doView = useCallback(
(rowData: Row) => {
Expand Down Expand Up @@ -90,10 +160,11 @@ export const WorkflowsTable = ({ items }: WorkflowsTableProps) => {

return (
<Table
title=""
options={{ search: true, paging: false, actionsColumnIndex: 1 }}
options={{ search: true, paging: false, actionsColumnIndex: 5 }}
columns={columns}
data={data}
filters={[{ column: 'Type', type: 'select' }]}
initialState={initTableState}
actions={[
{
icon: PlayArrow,
Expand Down
Loading

0 comments on commit 677e66c

Please sign in to comment.