mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 00:32:12 +02:00
manual and workflow commit.
This commit is contained in:
@@ -3,6 +3,7 @@ enum ComponentID {
|
||||
Log = 'log',
|
||||
Schedule = 'schedule',
|
||||
JavaScriptCode = 'javascript',
|
||||
Manual = 'manual'
|
||||
}
|
||||
|
||||
export default ComponentID;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import IconProp from '../../Icon/IconProp';
|
||||
import ComponentID from '../ComponentID';
|
||||
import ComponentMetadata, {
|
||||
ComponentInputType,
|
||||
ComponentType,
|
||||
@@ -6,7 +7,7 @@ import ComponentMetadata, {
|
||||
|
||||
const components: Array<ComponentMetadata> = [
|
||||
{
|
||||
id: 'manual',
|
||||
id: ComponentID.Manual,
|
||||
title: 'Manual',
|
||||
category: 'Utils',
|
||||
description: 'Run this workflow manually',
|
||||
|
||||
@@ -8,6 +8,13 @@ import {
|
||||
NodeDataProp,
|
||||
NodeType,
|
||||
} from 'Common/Types/Workflow/Component';
|
||||
import API from 'Common/Utils/API';
|
||||
import EmptyResponseData from 'Common/Types/API/EmptyResponse';
|
||||
import URL from 'Common/Types/API/URL';
|
||||
import Protocol from 'Common/Types/API/Protocol';
|
||||
import { WorkflowHostname } from '../Config';
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import ClusterKeyAuthorization from '../Middleware/ClusterKeyAuthorization';
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor(postgresDatabase?: PostgresDatabase) {
|
||||
@@ -56,6 +63,14 @@ export class Service extends DatabaseService<Model> {
|
||||
},
|
||||
});
|
||||
|
||||
await API.post<EmptyResponseData>(
|
||||
new URL(Protocol.HTTP, WorkflowHostname, new Route('/workflow/update/'+onUpdate.updateBy.query._id!)),
|
||||
{},
|
||||
{
|
||||
...ClusterKeyAuthorization.getClusterKeyHeaders(),
|
||||
}
|
||||
);
|
||||
|
||||
return onUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,9 +42,20 @@ export interface InitProps {
|
||||
) => Promise<void>;
|
||||
}
|
||||
|
||||
export interface UpdateProps {
|
||||
workflowId: ObjectID;
|
||||
}
|
||||
|
||||
export default class ComponentCode {
|
||||
private metadata: ComponentMetadata | null = null;
|
||||
|
||||
public executeWorkflow: ((executeWorkflow: ExecuteWorkflowType) => Promise<void>) | null = null;
|
||||
|
||||
public scheduleWorkflow: ((
|
||||
executeWorkflow: ExecuteWorkflowType,
|
||||
scheduleAt: string
|
||||
) => Promise<void>) | null = null;
|
||||
|
||||
public constructor() {}
|
||||
|
||||
public setMetadata(metadata: ComponentMetadata): void {
|
||||
@@ -59,10 +70,22 @@ export default class ComponentCode {
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
public async setupComponent(props: InitProps): Promise<void> {
|
||||
|
||||
this.executeWorkflow = props.executeWorkflow;
|
||||
this.scheduleWorkflow = props.scheduleWorkflow;
|
||||
|
||||
return await this.init(props);
|
||||
}
|
||||
|
||||
public async init(_props: InitProps): Promise<void> {
|
||||
return await Promise.resolve();
|
||||
}
|
||||
|
||||
public async update(_props: UpdateProps): Promise<void> {
|
||||
return await Promise.resolve();
|
||||
}
|
||||
|
||||
public async run(
|
||||
_args: JSONObject,
|
||||
_options: RunOptions
|
||||
|
||||
@@ -19,12 +19,14 @@ import UpdateManyBaseModel from './UpdateManyBaseModel';
|
||||
import OnDeleteBaseModel from './OnDeleteBaseModel';
|
||||
import DeleteOneBaseModel from './DeleteOneBaseModel';
|
||||
import DeleteManyBaseModel from './DeleteManyBaseMoidel';
|
||||
import ManualTrigger from './Manual';
|
||||
|
||||
const Components: Dictionary<ComponentCode> = {
|
||||
[ComponentID.Webhook]: new WebhookTrigger(),
|
||||
[ComponentID.Log]: new Log(),
|
||||
[ComponentID.Schedule]: new Schedule(),
|
||||
[ComponentID.JavaScriptCode]: new JavaScirptCode(),
|
||||
[ComponentID.Manual]: new ManualTrigger()
|
||||
};
|
||||
|
||||
for (const baseModelService of BaseModelServices) {
|
||||
|
||||
26
CommonServer/Types/Workflow/Components/Manual.ts
Normal file
26
CommonServer/Types/Workflow/Components/Manual.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
import ComponentMetadata from 'Common/Types/Workflow/Component';
|
||||
import ComponentID from 'Common/Types/Workflow/ComponentID';
|
||||
import ManualComponents from 'Common/Types/Workflow/Components/Manual';
|
||||
import ComponentCode, {
|
||||
InitProps,
|
||||
} from '../ComponentCode';
|
||||
|
||||
export default class ManualTrigger extends ComponentCode {
|
||||
public constructor() {
|
||||
super();
|
||||
const Component: ComponentMetadata | undefined =
|
||||
ManualComponents.find((i: ComponentMetadata) => {
|
||||
return i.id === ComponentID.Manual;
|
||||
});
|
||||
|
||||
if (!Component) {
|
||||
throw new BadDataException('Component not found.');
|
||||
}
|
||||
this.setMetadata(Component);
|
||||
}
|
||||
|
||||
public override async init(_props: InitProps): Promise<void> {
|
||||
// do nothing because its a manual component.
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import QueryHelper from '../../Database/QueryHelper';
|
||||
import ComponentCode, {
|
||||
ExecuteWorkflowType,
|
||||
InitProps,
|
||||
UpdateProps,
|
||||
} from '../ComponentCode';
|
||||
|
||||
export default class WebhookTrigger extends ComponentCode {
|
||||
@@ -61,4 +62,44 @@ export default class WebhookTrigger extends ComponentCode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override async update(props: UpdateProps): Promise<void> {
|
||||
const workflow: Workflow | null = await WorkflowService.findOneBy({
|
||||
query: {
|
||||
triggerId: ComponentID.Schedule,
|
||||
_id: props.workflowId.toString(),
|
||||
triggerArguments: QueryHelper.notNull(),
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
triggerArguments: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
}
|
||||
});
|
||||
|
||||
if(!workflow){
|
||||
return;
|
||||
}
|
||||
|
||||
if(!this.scheduleWorkflow){
|
||||
return;
|
||||
}
|
||||
|
||||
const executeWorkflow: ExecuteWorkflowType = {
|
||||
workflowId: new ObjectID(workflow._id!),
|
||||
returnValues: {},
|
||||
};
|
||||
|
||||
if (
|
||||
workflow.triggerArguments &&
|
||||
workflow.triggerArguments['schedule']
|
||||
) {
|
||||
await this.scheduleWorkflow(
|
||||
executeWorkflow,
|
||||
workflow.triggerArguments['schedule'] as string
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,10 @@ export const componentInputTypeToFormFieldType: Function = (
|
||||
return {
|
||||
fieldType: FormFieldSchemaType.Dropdown,
|
||||
dropdownOptions: [
|
||||
{
|
||||
label: 'Every Minute',
|
||||
value: '* * * * *',
|
||||
},
|
||||
{
|
||||
label: 'Every 30 minutes',
|
||||
value: '*/30 * * * *',
|
||||
|
||||
74
Workflow/API/Workflow.ts
Normal file
74
Workflow/API/Workflow.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import Express, {
|
||||
ExpressRequest,
|
||||
ExpressResponse,
|
||||
ExpressRouter,
|
||||
} from 'CommonServer/Utils/Express';
|
||||
import Response from 'CommonServer/Utils/Response';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
import WorkflowService from 'CommonServer/Services/WorkflowService';
|
||||
import Workflow from 'Model/Models/Workflow';
|
||||
import ClusterKeyAuthorization from 'CommonServer/Middleware/ClusterKeyAuthorization';
|
||||
import ComponentCode from 'CommonServer/Types/Workflow/ComponentCode';
|
||||
import Components from 'CommonServer/Types/Workflow/Components/Index';
|
||||
|
||||
export default class WorkflowAPI {
|
||||
public router!: ExpressRouter;
|
||||
|
||||
public constructor() {
|
||||
this.router = Express.getRouter();
|
||||
|
||||
this.router.get(`/update/:workflowId`, ClusterKeyAuthorization.isAuthorizedServiceMiddleware, this.updateWorkflow);
|
||||
|
||||
this.router.post(`/update/:workflowId`, ClusterKeyAuthorization.isAuthorizedServiceMiddleware, this.updateWorkflow);
|
||||
}
|
||||
|
||||
public async updateWorkflow(
|
||||
req: ExpressRequest,
|
||||
res: ExpressResponse
|
||||
): Promise<void> {
|
||||
// add this workflow to the run queue and return the 200 response.
|
||||
|
||||
if (!req.params['workflowId']) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadDataException('workflowId not found in URL')
|
||||
);
|
||||
}
|
||||
|
||||
const workflow: Workflow | null = await WorkflowService.findOneById({
|
||||
id: new ObjectID(req.params['workflowId']),
|
||||
select: {
|
||||
_id: true,
|
||||
triggerId: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
}
|
||||
});
|
||||
|
||||
if(!workflow){
|
||||
return Response.sendJsonObjectResponse(req, res, {
|
||||
status: 'Workflow not found',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const componentCode: ComponentCode | undefined = Components[workflow.triggerId as string];
|
||||
|
||||
if(!componentCode){
|
||||
return Response.sendJsonObjectResponse(req, res, {
|
||||
status: 'Component not found',
|
||||
});
|
||||
}
|
||||
|
||||
await componentCode.update({
|
||||
workflowId: workflow.id!
|
||||
});
|
||||
|
||||
return Response.sendJsonObjectResponse(req, res, {
|
||||
status: 'Updated',
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import QueueWorker from 'CommonServer/Infrastructure/QueueWorker';
|
||||
import RunWorkflow from './Services/RunWorkflow';
|
||||
import { JSONObject } from 'Common/Types/JSON';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import WorkflowAPI from './API/Workflow';
|
||||
|
||||
const APP_NAME: string = 'workflow';
|
||||
|
||||
@@ -21,6 +22,8 @@ const app: ExpressApplication = Express.getExpressApp();
|
||||
|
||||
app.use(`/${APP_NAME}/manual`, new ManualAPI().router);
|
||||
|
||||
app.use(`/${APP_NAME}`, new WorkflowAPI().router);
|
||||
|
||||
app.get(
|
||||
`/${APP_NAME}/docs/:componentName`,
|
||||
(req: ExpressRequest, res: ExpressResponse) => {
|
||||
|
||||
Reference in New Issue
Block a user