From 23462dec74ee24558ae426286ca243db07e059c4 Mon Sep 17 00:00:00 2001 From: Maximilian Kuhn Date: Mon, 24 Jul 2023 15:16:10 +0200 Subject: [PATCH 1/8] Add On-Demand Deployment Pop-Up --- .../deployment/services/DeploymentPlugin.js | 61 ++++++++++++++++--- .../ServiceDeploymentTransformationModal.js | 45 ++++++++++++++ 2 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 components/bpmn-q/modeler-component/extensions/opentosca/ui/deployment/services/ServiceDeploymentTransformationModal.js diff --git a/components/bpmn-q/modeler-component/extensions/opentosca/ui/deployment/services/DeploymentPlugin.js b/components/bpmn-q/modeler-component/extensions/opentosca/ui/deployment/services/DeploymentPlugin.js index 047baa3b..b06b14a6 100644 --- a/components/bpmn-q/modeler-component/extensions/opentosca/ui/deployment/services/DeploymentPlugin.js +++ b/components/bpmn-q/modeler-component/extensions/opentosca/ui/deployment/services/DeploymentPlugin.js @@ -15,6 +15,7 @@ import React, {Fragment, PureComponent} from 'react'; import ServiceDeploymentOverviewModal from './ServiceDeploymentOverviewModal'; import ServiceDeploymentInputModal from './ServiceDeploymentInputModal'; import ServiceDeploymentBindingModal from './ServiceDeploymentBindingModal'; +import ServiceDeploymentTransformationModal from './ServiceDeploymentTransformationModal'; import {createServiceInstance, uploadCSARToContainer} from '../../../deployment/OpenTOSCAUtils'; import {bindUsingPull, bindUsingPush} from '../../../deployment/BindingUtils'; @@ -25,6 +26,7 @@ import {getRootProcess} from '../../../../../editor/util/ModellingUtilities'; import ExtensibleButton from "../../../../../editor/ui/ExtensibleButton"; const defaultState = { + windowOpenDeploymentTransformation: false, windowOpenDeploymentOverview: false, windowOpenDeploymentInput: false, windowOpenDeploymentBinding: false @@ -40,6 +42,7 @@ export default class DeploymentPlugin extends PureComponent { this.handleDeploymentOverviewClosed = this.handleDeploymentOverviewClosed.bind(this); this.handleDeploymentInputClosed = this.handleDeploymentInputClosed.bind(this); this.handleDeploymentBindingClosed = this.handleDeploymentBindingClosed.bind(this); + this.handleDeploymentTransformationClosed = this.handleDeploymentTransformationClosed.bind(this); } componentDidMount() { @@ -106,7 +109,8 @@ export default class DeploymentPlugin extends PureComponent { this.setState({ windowOpenDeploymentOverview: false, windowOpenDeploymentInput: false, - windowOpenDeploymentBinding: false + windowOpenDeploymentBinding: false, + windowOpenDeploymentTransformation: false }); return; } @@ -125,6 +129,7 @@ export default class DeploymentPlugin extends PureComponent { windowOpenDeploymentOverview: false, windowOpenDeploymentInput: true, windowOpenDeploymentBinding: false, + windowOpenDeploymentTransformation: false, csarList: csarList }); return; @@ -134,7 +139,8 @@ export default class DeploymentPlugin extends PureComponent { this.setState({ windowOpenDeploymentOverview: false, windowOpenDeploymentInput: false, - windowOpenDeploymentBinding: false + windowOpenDeploymentBinding: false, + windowOpenDeploymentTransformation: false }); } @@ -178,7 +184,8 @@ export default class DeploymentPlugin extends PureComponent { this.setState({ windowOpenDeploymentOverview: false, windowOpenDeploymentInput: false, - windowOpenDeploymentBinding: false + windowOpenDeploymentBinding: false, + windowOpenDeploymentTransformation: false }); return; } @@ -198,7 +205,8 @@ export default class DeploymentPlugin extends PureComponent { this.setState({ windowOpenDeploymentOverview: false, windowOpenDeploymentInput: false, - windowOpenDeploymentBinding: true + windowOpenDeploymentBinding: true, + windowOpenDeploymentTransformation: false }); return; } @@ -207,7 +215,8 @@ export default class DeploymentPlugin extends PureComponent { this.setState({ windowOpenDeploymentOverview: false, windowOpenDeploymentInput: false, - windowOpenDeploymentBinding: false + windowOpenDeploymentBinding: false, + windowOpenDeploymentTransformation: false }); } @@ -252,7 +261,8 @@ export default class DeploymentPlugin extends PureComponent { this.setState({ windowOpenDeploymentOverview: false, windowOpenDeploymentInput: false, - windowOpenDeploymentBinding: false + windowOpenDeploymentBinding: false, + windowOpenDeploymentTransformation: false }); return; } @@ -271,7 +281,8 @@ export default class DeploymentPlugin extends PureComponent { this.setState({ windowOpenDeploymentOverview: false, windowOpenDeploymentInput: false, - windowOpenDeploymentBinding: false + windowOpenDeploymentBinding: false, + windowOpenDeploymentTransformation: false }); } @@ -306,6 +317,34 @@ export default class DeploymentPlugin extends PureComponent { }); } + /** + * Handle the result of a close operation on the tramfpr,atopm + * + * @param result the result from the close operation + */ + handleDeploymentTransformationClosed(result) { + console.log(result); + if (result && result.hasOwnProperty('onDemand')) { + if (result.onDemand === true) { + //TODO: Cooles Deployment + } + this.setState({ + windowOpenDeploymentOverview: true, + windowOpenDeploymentInput: false, + windowOpenDeploymentBinding: false, + windowOpenDeploymentTransformation: false + }); + return; + } + // handle cancellation + this.setState({ + windowOpenDeploymentOverview: false, + windowOpenDeploymentInput: false, + windowOpenDeploymentBinding: false, + windowOpenDeploymentTransformation: false + }); + } + render() { // render deployment button and pop-up menu return ( @@ -325,10 +364,16 @@ export default class DeploymentPlugin extends PureComponent { className="qwm-indent">Hide Deployment , ]}/> + {this.state.windowOpenDeploymentTransformation && ( + + )} {this.state.windowOpenDeploymentOverview && (

{children}

); +const Body = Modal.Body || (({children}) =>
{children}
); +const Footer = Modal.Footer || (({children}) =>
{children}
); + +export default function ServiceDeploymentTransformationModal({onClose, initValues}) { + + // close if no deployment required + if (!initValues || initValues.length === 0) { + onClose(); + } + + const onOnDemand = (value) => onClose({ + onDemand: value, + }); + + return + + + Enable On Demand Service Deployment? + +
+
+ + +
+
+
; +} From fe83257ed1a560c5b4368e8007b1acd8aebf9da0 Mon Sep 17 00:00:00 2001 From: Maximilian Kuhn Date: Thu, 27 Jul 2023 16:46:43 +0200 Subject: [PATCH 2/8] Fix button integration --- .../editor/ui/DeploymentButton.js | 50 +++++++++++++++++-- .../ui/OnDemandDeploymentModal.js} | 10 +--- .../deployment/services/DeploymentPlugin.js | 47 +---------------- 3 files changed, 49 insertions(+), 58 deletions(-) rename components/bpmn-q/modeler-component/{extensions/opentosca/ui/deployment/services/ServiceDeploymentTransformationModal.js => editor/ui/OnDemandDeploymentModal.js} (77%) diff --git a/components/bpmn-q/modeler-component/editor/ui/DeploymentButton.js b/components/bpmn-q/modeler-component/editor/ui/DeploymentButton.js index e6cb6c17..dfa74426 100644 --- a/components/bpmn-q/modeler-component/editor/ui/DeploymentButton.js +++ b/components/bpmn-q/modeler-component/editor/ui/DeploymentButton.js @@ -1,8 +1,15 @@ -import React from 'react'; +import React, { Fragment, useState } from 'react'; import NotificationHandler from './notifications/NotificationHandler'; import {deployWorkflowToCamunda} from '../util/IoUtilities'; import {getCamundaEndpoint} from '../config/EditorConfigManager'; import {getRootProcess} from '../util/ModellingUtilities'; +import {getServiceTasksToDeploy} from '../../extensions/opentosca/deployment/DeploymentUtils'; +import { getModeler } from '../ModelerHandler'; +import OnDemandDeploymentModal from './OnDemandDeploymentModal'; + +const defaultState = { + windowOpenOnDemandDeployment: false, +}; /** * React button for starting the deployment of the workflow. @@ -12,9 +19,30 @@ import {getRootProcess} from '../util/ModellingUtilities'; * @constructor */ export default function DeploymentButton(props) { + const [windowOpenOnDemandDeployment, setWindowOpenOnDemandDeployment] = useState(false); const {modeler} = props; + + /** + * Handle the result of a close operation on the tramfpr,atopm + * + * @param result the result from the close operation + */ + async function handleOnDemandDeployment(result) { + console.log(result); + if (result && result.hasOwnProperty('onDemand')) { + if (result.onDemand === true) { + //TODO: Cooles Deployment + } + // deploy in any case + deploy(); + } + // handle cancellation (don't deploy) + setWindowOpenOnDemandDeployment(false); + + } + /** * Deploy the current workflow to the Camunda engine */ @@ -56,12 +84,26 @@ export default function DeploymentButton(props) { } } + async function onClick() { + let csarsToDeploy = getServiceTasksToDeploy(getRootProcess(getModeler().getDefinitions())); + if (csarsToDeploy.length > 0) { + setWindowOpenOnDemandDeployment(true); + } else { + deploy(); + } + } + return ( - <> + - + {windowOpenOnDemandDeployment && ( + handleOnDemandDeployment(e)} + /> + )} + ); } \ No newline at end of file diff --git a/components/bpmn-q/modeler-component/extensions/opentosca/ui/deployment/services/ServiceDeploymentTransformationModal.js b/components/bpmn-q/modeler-component/editor/ui/OnDemandDeploymentModal.js similarity index 77% rename from components/bpmn-q/modeler-component/extensions/opentosca/ui/deployment/services/ServiceDeploymentTransformationModal.js rename to components/bpmn-q/modeler-component/editor/ui/OnDemandDeploymentModal.js index be3ad5f0..46c0850c 100644 --- a/components/bpmn-q/modeler-component/extensions/opentosca/ui/deployment/services/ServiceDeploymentTransformationModal.js +++ b/components/bpmn-q/modeler-component/editor/ui/OnDemandDeploymentModal.js @@ -13,18 +13,12 @@ import React from 'react'; // polyfill upcoming structural components -import Modal from "../../../../../editor/ui/modal/Modal"; +import Modal from './modal/Modal'; const Title = Modal.Title || (({children}) =>

{children}

); -const Body = Modal.Body || (({children}) =>
{children}
); const Footer = Modal.Footer || (({children}) =>
{children}
); -export default function ServiceDeploymentTransformationModal({onClose, initValues}) { - - // close if no deployment required - if (!initValues || initValues.length === 0) { - onClose(); - } +export default function OnDemandDeploymentModal({onClose}) { const onOnDemand = (value) => onClose({ onDemand: value, diff --git a/components/bpmn-q/modeler-component/extensions/opentosca/ui/deployment/services/DeploymentPlugin.js b/components/bpmn-q/modeler-component/extensions/opentosca/ui/deployment/services/DeploymentPlugin.js index b06b14a6..cbb9325b 100644 --- a/components/bpmn-q/modeler-component/extensions/opentosca/ui/deployment/services/DeploymentPlugin.js +++ b/components/bpmn-q/modeler-component/extensions/opentosca/ui/deployment/services/DeploymentPlugin.js @@ -15,7 +15,6 @@ import React, {Fragment, PureComponent} from 'react'; import ServiceDeploymentOverviewModal from './ServiceDeploymentOverviewModal'; import ServiceDeploymentInputModal from './ServiceDeploymentInputModal'; import ServiceDeploymentBindingModal from './ServiceDeploymentBindingModal'; -import ServiceDeploymentTransformationModal from './ServiceDeploymentTransformationModal'; import {createServiceInstance, uploadCSARToContainer} from '../../../deployment/OpenTOSCAUtils'; import {bindUsingPull, bindUsingPush} from '../../../deployment/BindingUtils'; @@ -26,7 +25,6 @@ import {getRootProcess} from '../../../../../editor/util/ModellingUtilities'; import ExtensibleButton from "../../../../../editor/ui/ExtensibleButton"; const defaultState = { - windowOpenDeploymentTransformation: false, windowOpenDeploymentOverview: false, windowOpenDeploymentInput: false, windowOpenDeploymentBinding: false @@ -42,7 +40,6 @@ export default class DeploymentPlugin extends PureComponent { this.handleDeploymentOverviewClosed = this.handleDeploymentOverviewClosed.bind(this); this.handleDeploymentInputClosed = this.handleDeploymentInputClosed.bind(this); this.handleDeploymentBindingClosed = this.handleDeploymentBindingClosed.bind(this); - this.handleDeploymentTransformationClosed = this.handleDeploymentTransformationClosed.bind(this); } componentDidMount() { @@ -110,7 +107,6 @@ export default class DeploymentPlugin extends PureComponent { windowOpenDeploymentOverview: false, windowOpenDeploymentInput: false, windowOpenDeploymentBinding: false, - windowOpenDeploymentTransformation: false }); return; } @@ -129,7 +125,6 @@ export default class DeploymentPlugin extends PureComponent { windowOpenDeploymentOverview: false, windowOpenDeploymentInput: true, windowOpenDeploymentBinding: false, - windowOpenDeploymentTransformation: false, csarList: csarList }); return; @@ -140,7 +135,6 @@ export default class DeploymentPlugin extends PureComponent { windowOpenDeploymentOverview: false, windowOpenDeploymentInput: false, windowOpenDeploymentBinding: false, - windowOpenDeploymentTransformation: false }); } @@ -185,7 +179,6 @@ export default class DeploymentPlugin extends PureComponent { windowOpenDeploymentOverview: false, windowOpenDeploymentInput: false, windowOpenDeploymentBinding: false, - windowOpenDeploymentTransformation: false }); return; } @@ -206,7 +199,6 @@ export default class DeploymentPlugin extends PureComponent { windowOpenDeploymentOverview: false, windowOpenDeploymentInput: false, windowOpenDeploymentBinding: true, - windowOpenDeploymentTransformation: false }); return; } @@ -216,7 +208,6 @@ export default class DeploymentPlugin extends PureComponent { windowOpenDeploymentOverview: false, windowOpenDeploymentInput: false, windowOpenDeploymentBinding: false, - windowOpenDeploymentTransformation: false }); } @@ -262,7 +253,6 @@ export default class DeploymentPlugin extends PureComponent { windowOpenDeploymentOverview: false, windowOpenDeploymentInput: false, windowOpenDeploymentBinding: false, - windowOpenDeploymentTransformation: false }); return; } @@ -282,7 +272,6 @@ export default class DeploymentPlugin extends PureComponent { windowOpenDeploymentOverview: false, windowOpenDeploymentInput: false, windowOpenDeploymentBinding: false, - windowOpenDeploymentTransformation: false }); } @@ -317,34 +306,6 @@ export default class DeploymentPlugin extends PureComponent { }); } - /** - * Handle the result of a close operation on the tramfpr,atopm - * - * @param result the result from the close operation - */ - handleDeploymentTransformationClosed(result) { - console.log(result); - if (result && result.hasOwnProperty('onDemand')) { - if (result.onDemand === true) { - //TODO: Cooles Deployment - } - this.setState({ - windowOpenDeploymentOverview: true, - windowOpenDeploymentInput: false, - windowOpenDeploymentBinding: false, - windowOpenDeploymentTransformation: false - }); - return; - } - // handle cancellation - this.setState({ - windowOpenDeploymentOverview: false, - windowOpenDeploymentInput: false, - windowOpenDeploymentBinding: false, - windowOpenDeploymentTransformation: false - }); - } - render() { // render deployment button and pop-up menu return ( @@ -364,16 +325,10 @@ export default class DeploymentPlugin extends PureComponent { className="qwm-indent">Hide Deployment , ]}/> - {this.state.windowOpenDeploymentTransformation && ( - - )} {this.state.windowOpenDeploymentOverview && ( Date: Sat, 29 Jul 2023 13:06:38 +0200 Subject: [PATCH 3/8] implement on demand transformation --- .../editor/ui/DeploymentButton.js | 5 +- .../opentosca/deployment/BindingUtils.js | 17 ++++- .../opentosca/deployment/DeploymentUtils.js | 2 +- .../opentosca/modeling/OpenTOSCARenderer.js | 4 +- .../replacement/OnDemandTransformator.js | 70 +++++++++++++++++++ .../deployment/services/DeploymentPlugin.js | 2 +- 6 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 components/bpmn-q/modeler-component/extensions/opentosca/replacement/OnDemandTransformator.js diff --git a/components/bpmn-q/modeler-component/editor/ui/DeploymentButton.js b/components/bpmn-q/modeler-component/editor/ui/DeploymentButton.js index dfa74426..6a230c4d 100644 --- a/components/bpmn-q/modeler-component/editor/ui/DeploymentButton.js +++ b/components/bpmn-q/modeler-component/editor/ui/DeploymentButton.js @@ -6,6 +6,7 @@ import {getRootProcess} from '../util/ModellingUtilities'; import {getServiceTasksToDeploy} from '../../extensions/opentosca/deployment/DeploymentUtils'; import { getModeler } from '../ModelerHandler'; import OnDemandDeploymentModal from './OnDemandDeploymentModal'; +import {startOnDemandReplacementProcess} from "../../extensions/opentosca/replacement/OnDemandTransformator"; const defaultState = { windowOpenOnDemandDeployment: false, @@ -33,7 +34,9 @@ export default function DeploymentButton(props) { console.log(result); if (result && result.hasOwnProperty('onDemand')) { if (result.onDemand === true) { - //TODO: Cooles Deployment + const xml = (await modeler.saveXML({format: true})).xml; + console.log("Post Transfrom", await startOnDemandReplacementProcess(xml)); + } // deploy in any case deploy(); diff --git a/components/bpmn-q/modeler-component/extensions/opentosca/deployment/BindingUtils.js b/components/bpmn-q/modeler-component/extensions/opentosca/deployment/BindingUtils.js index 4e8a81cd..c6b721a7 100644 --- a/components/bpmn-q/modeler-component/extensions/opentosca/deployment/BindingUtils.js +++ b/components/bpmn-q/modeler-component/extensions/opentosca/deployment/BindingUtils.js @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ +import * as config from "../framework-config/config-manager"; const QUANTME_NAMESPACE_PULL_ENCODED = encodeURIComponent(encodeURIComponent('http://quantil.org/quantme/pull')); const QUANTME_NAMESPACE_PUSH_ENCODED = encodeURIComponent(encodeURIComponent('http://quantil.org/quantme/push')); @@ -48,9 +49,9 @@ export function getBindingType(serviceTask) { * @param modeling the modeling element to adapt properties of the workflow elements * @return {{success: boolean}} true if binding is successful, false otherwise */ -export function bindUsingPull(topicName, serviceTaskId, elementRegistry, modeling) { +export function bindUsingPull(csar, serviceTaskId, elementRegistry, modeling) { - if (topicName === undefined || serviceTaskId === undefined || elementRegistry === undefined || modeling === undefined) { + if (csar.topicName === undefined || serviceTaskId === undefined || elementRegistry === undefined || modeling === undefined) { console.error('Topic name, service task id, element registry, and modeling required for binding using pull!'); return {success: false}; } @@ -62,8 +63,18 @@ export function bindUsingPull(topicName, serviceTaskId, elementRegistry, modelin return {success: false}; } + let deploymentModelUrl = serviceTask.businessObject.get('opentosca:deploymentModelUrl'); + if (deploymentModelUrl.startsWith('{{ wineryEndpoint }}')) { + deploymentModelUrl = deploymentModelUrl.replace('{{ wineryEndpoint }}', config.getWineryEndpoint()); + } + // remove deployment model URL and set topic - modeling.updateProperties(serviceTask, {'deploymentModelUrl': undefined, type: 'external', topic: topicName}); + modeling.updateProperties(serviceTask, { + 'opentosca:deploymentModelUrl': deploymentModelUrl, + 'opentosca:deploymentBuildPlanInstanceUrl': csar.buildPlanUrl, + type: 'external', + topic: csar.topicName + }); return {success: true}; } diff --git a/components/bpmn-q/modeler-component/extensions/opentosca/deployment/DeploymentUtils.js b/components/bpmn-q/modeler-component/extensions/opentosca/deployment/DeploymentUtils.js index 46877eb9..018e2670 100644 --- a/components/bpmn-q/modeler-component/extensions/opentosca/deployment/DeploymentUtils.js +++ b/components/bpmn-q/modeler-component/extensions/opentosca/deployment/DeploymentUtils.js @@ -72,6 +72,6 @@ function getCSARName(serviceTask) { * @param element the element to check * @return {*|boolean} true if the element is a ServiceTask and has an assigned deployment model, false otherwise */ -function isDeployableServiceTask(element) { +export function isDeployableServiceTask(element) { return element.$type && element.$type === 'bpmn:ServiceTask' && element.deploymentModelUrl && getBindingType(element) !== undefined; } diff --git a/components/bpmn-q/modeler-component/extensions/opentosca/modeling/OpenTOSCARenderer.js b/components/bpmn-q/modeler-component/extensions/opentosca/modeling/OpenTOSCARenderer.js index 1cf77329..149c5a89 100644 --- a/components/bpmn-q/modeler-component/extensions/opentosca/modeling/OpenTOSCARenderer.js +++ b/components/bpmn-q/modeler-component/extensions/opentosca/modeling/OpenTOSCARenderer.js @@ -235,7 +235,7 @@ export default class OpenTOSCARenderer extends BpmnRenderer { const commands = []; if (shifts.right || shifts.left) { - const xPosition = (newBoundingBox.left + newBoundingBox.right) / 2 + const xPosition = (newBoundingBox.left + newBoundingBox.right) / 2; for (const otherElement of allElements) { let otherXPosition = element.x + NODE_WIDTH / 2; const otherElementBoundingBox = this.currentlyShownDeploymentsModels.get(otherElement.id)?.boundingBox; @@ -248,7 +248,7 @@ export default class OpenTOSCARenderer extends BpmnRenderer { } else if (shifts.left && otherXPosition <= xPosition && otherElement.id !== element.id) { xShift = -shifts.left - NODE_SHIFT_MARGIN } else { - continue + continue; } // Can not move elements without parent if(!otherElement.parent) continue; diff --git a/components/bpmn-q/modeler-component/extensions/opentosca/replacement/OnDemandTransformator.js b/components/bpmn-q/modeler-component/extensions/opentosca/replacement/OnDemandTransformator.js new file mode 100644 index 00000000..e3a1880a --- /dev/null +++ b/components/bpmn-q/modeler-component/extensions/opentosca/replacement/OnDemandTransformator.js @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2023 Institute of Architecture of Application Systems - + * University of Stuttgart + * + * This program and the accompanying materials are made available under the + * terms the Apache Software License 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import {createTempModelerFromXml} from '../../../editor/ModelerHandler'; +import { + getRootProcess, +} from '../../../editor/util/ModellingUtilities'; +import {getXml} from '../../../editor/util/IoUtilities'; +import {isDeployableServiceTask} from "../deployment/DeploymentUtils"; +import * as config from "../framework-config/config-manager"; + +/** + * Initiate the replacement process for the QuantME tasks that are contained in the current process model + * + * @param xml the BPMN diagram in XML format + * @param currentQRMs the set of currently in the framework available QRMs + * @param endpointConfig endpoints of the services required for the dynamic hardware selection + */ +export async function startOnDemandReplacementProcess(xml) { + const modeler = await createTempModelerFromXml(xml); + const modeling = modeler.get('modeling'); + const elementRegistry = modeler.get('elementRegistry'); + const bpmnReplace = modeler.get('bpmnReplace'); + const bpmnAutoResizeProvider = modeler.get('bpmnAutoResizeProvider'); + bpmnAutoResizeProvider.canResize = () => false; + + const serviceTasks = elementRegistry.filter(({businessObject}) => isDeployableServiceTask(businessObject)); + + for (const serviceTask of serviceTasks) { + const bounds = { + x: serviceTask.x, + y: serviceTask.y, + }; + let deploymentModelUrl = serviceTask.businessObject.get('opentosca:deploymentModelUrl'); + if (deploymentModelUrl.startsWith('{{ wineryEndpoint }}')) { + deploymentModelUrl = deploymentModelUrl.replace('{{ wineryEndpoint }}', config.getWineryEndpoint()); + } + let subProcess = bpmnReplace.replaceElement(serviceTask, {type: 'bpmn:SubProcess'}); + + subProcess.businessObject.set("opentosca:onDemandDeployment", true); + subProcess.businessObject.set("opentosca:deploymentModelUrl", deploymentModelUrl); + + const startEvent = modeling.createShape({ + type: 'bpmn:StartEvent' + }, {x: 200, y: 200}, subProcess); + + + const serviceTask1 = modeling.appendShape(startEvent, { + type: 'bpmn:ServiceTask' + }, {x: 400, y: 200}); + + + const serviceTask2 = modeling.appendShape(serviceTask1, { + type: 'bpmn:ServiceTask' + }, {x: 600, y: 200}, subProcess); + } + + // layout diagram after successful transformation + let updated_xml = await getXml(modeler); + console.log(updated_xml); + return {status: 'transformed', xml: updated_xml}; +} diff --git a/components/bpmn-q/modeler-component/extensions/opentosca/ui/deployment/services/DeploymentPlugin.js b/components/bpmn-q/modeler-component/extensions/opentosca/ui/deployment/services/DeploymentPlugin.js index cbb9325b..710fb2af 100644 --- a/components/bpmn-q/modeler-component/extensions/opentosca/ui/deployment/services/DeploymentPlugin.js +++ b/components/bpmn-q/modeler-component/extensions/opentosca/ui/deployment/services/DeploymentPlugin.js @@ -232,7 +232,7 @@ export default class DeploymentPlugin extends PureComponent { // bind the service instance using the specified binding pattern let bindingResponse = undefined; if (csar.type === 'pull') { - bindingResponse = bindUsingPull(csar.topicName, serviceTaskIds[j], this.modeler.get('elementRegistry'), this.modeler.get('modeling')); + bindingResponse = bindUsingPull(csar, serviceTaskIds[j], this.modeler.get('elementRegistry'), this.modeler.get('modeling')); } else if (csar.type === 'push') { bindingResponse = bindUsingPush(csar, serviceTaskIds[j], this.modeler.get('elementRegistry')); } From 6220a5a8d668a0f91f8e5d6cd265be70c94bfade Mon Sep 17 00:00:00 2001 From: Christoph Walcher Date: Wed, 2 Aug 2023 09:51:31 +0200 Subject: [PATCH 4/8] upload transformed xml --- .../modeler-component/editor/ui/DeploymentButton.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/components/bpmn-q/modeler-component/editor/ui/DeploymentButton.js b/components/bpmn-q/modeler-component/editor/ui/DeploymentButton.js index 6a230c4d..4f3dff20 100644 --- a/components/bpmn-q/modeler-component/editor/ui/DeploymentButton.js +++ b/components/bpmn-q/modeler-component/editor/ui/DeploymentButton.js @@ -33,13 +33,15 @@ export default function DeploymentButton(props) { async function handleOnDemandDeployment(result) { console.log(result); if (result && result.hasOwnProperty('onDemand')) { + // get XML of the current workflow + let xml = (await modeler.saveXML({format: true})).xml; + if (result.onDemand === true) { - const xml = (await modeler.saveXML({format: true})).xml; - console.log("Post Transfrom", await startOnDemandReplacementProcess(xml)); + xml = await startOnDemandReplacementProcess(xml); } // deploy in any case - deploy(); + deploy(xml); } // handle cancellation (don't deploy) setWindowOpenOnDemandDeployment(false); @@ -49,7 +51,7 @@ export default function DeploymentButton(props) { /** * Deploy the current workflow to the Camunda engine */ - async function deploy() { + async function deploy(xml) { NotificationHandler.getInstance().displayNotification({ title: 'Deployment started', @@ -58,7 +60,6 @@ export default function DeploymentButton(props) { // get XML of the current workflow const rootElement = getRootProcess(modeler.getDefinitions()); - const xml = (await modeler.saveXML({format: true})).xml; // check if there are views defined for the modeler and include them in the deployment let viewsDict = {}; From 09fcb15dea096e16da6c006017de78c684251222 Mon Sep 17 00:00:00 2001 From: Christoph Walcher Date: Mon, 28 Aug 2023 21:27:41 +0200 Subject: [PATCH 5/8] Prototyp script task --- .../editor/ui/DeploymentButton.js | 11 ++- .../replacement/OnDemandTransformator.js | 75 +++++++++++++++++-- 2 files changed, 72 insertions(+), 14 deletions(-) diff --git a/components/bpmn-q/modeler-component/editor/ui/DeploymentButton.js b/components/bpmn-q/modeler-component/editor/ui/DeploymentButton.js index 4f3dff20..e4b5c242 100644 --- a/components/bpmn-q/modeler-component/editor/ui/DeploymentButton.js +++ b/components/bpmn-q/modeler-component/editor/ui/DeploymentButton.js @@ -1,10 +1,10 @@ -import React, { Fragment, useState } from 'react'; +import React, {Fragment, useState} from 'react'; import NotificationHandler from './notifications/NotificationHandler'; import {deployWorkflowToCamunda} from '../util/IoUtilities'; import {getCamundaEndpoint} from '../config/EditorConfigManager'; import {getRootProcess} from '../util/ModellingUtilities'; import {getServiceTasksToDeploy} from '../../extensions/opentosca/deployment/DeploymentUtils'; -import { getModeler } from '../ModelerHandler'; +import {getModeler} from '../ModelerHandler'; import OnDemandDeploymentModal from './OnDemandDeploymentModal'; import {startOnDemandReplacementProcess} from "../../extensions/opentosca/replacement/OnDemandTransformator"; @@ -35,17 +35,16 @@ export default function DeploymentButton(props) { if (result && result.hasOwnProperty('onDemand')) { // get XML of the current workflow let xml = (await modeler.saveXML({format: true})).xml; - + console.log("XML", xml) if (result.onDemand === true) { xml = await startOnDemandReplacementProcess(xml); - } // deploy in any case deploy(xml); } // handle cancellation (don't deploy) setWindowOpenOnDemandDeployment(false); - + } /** @@ -93,7 +92,7 @@ export default function DeploymentButton(props) { if (csarsToDeploy.length > 0) { setWindowOpenOnDemandDeployment(true); } else { - deploy(); + deploy((await modeler.saveXML({format: true})).xml); } } diff --git a/components/bpmn-q/modeler-component/extensions/opentosca/replacement/OnDemandTransformator.js b/components/bpmn-q/modeler-component/extensions/opentosca/replacement/OnDemandTransformator.js index e3a1880a..594a5fca 100644 --- a/components/bpmn-q/modeler-component/extensions/opentosca/replacement/OnDemandTransformator.js +++ b/components/bpmn-q/modeler-component/extensions/opentosca/replacement/OnDemandTransformator.js @@ -17,6 +17,57 @@ import {getXml} from '../../../editor/util/IoUtilities'; import {isDeployableServiceTask} from "../deployment/DeploymentUtils"; import * as config from "../framework-config/config-manager"; + +function createDeploymentScript(params) { + return ` +var params = ${JSON.stringify(params)}; + +function fetch(method, url, body) { + var resourceURL = new java.net.URL(url); + + var urlConnection = resourceURL.openConnection(); + urlConnection.setRequestMethod(method); + if (body) { + urlConnection.setDoOutput(true); + urlConnection.setRequestProperty("Content-Type", "application/json"); + var outputStream = urlConnection.getOutputStream() + var outputStreamWriter = new java.io.OutputStreamWriter(outputStream) + outputStreamWriter.write(body); + outputStreamWriter.flush(); + outputStreamWriter.close(); + outputStream.close(); + } + + var inputStream = new java.io.InputStreamReader(urlConnection + .getInputStream()); + var bufferedReader = new java.io.BufferedReader(inputStream); + var inputLine = "" + var text = ""; + var i = 5; + while ((inputLine = bufferedReader.readLine()) != null) { + text += inputLine + } + bufferedReader.close(); + return text; +} + + +var createCsarResponse = fetch('POST', params.opentoscaEndpoint, JSON.stringify({ + enrich: 'false', + name: params.csarName, + url: params.deploymentModelUrl +})) + + +var serviceTemplates = JSON.parse(fetch('GET', params.opentoscaEndpoint + "/" + params.csarName + ".csar/servicetemplates")) +var buildPlansUrl = serviceTemplates.service_templates[0]._links.self.href + '/buildplans' +var buildPlans = JSON.parse(fetch('GET', buildPlansUrl)) +var buildPlanUrl = buildPlans.plans[0]._links.self.href + +var createInstanceResponse = fetch('POST', buildPlanUrl + "/instances", JSON.stringify([])) +execution.setVariable(params.subprocessId + "_deploymentBuildPlanInstanceUrl", createInstanceResponse);`; +} + /** * Initiate the replacement process for the QuantME tasks that are contained in the current process model * @@ -35,10 +86,6 @@ export async function startOnDemandReplacementProcess(xml) { const serviceTasks = elementRegistry.filter(({businessObject}) => isDeployableServiceTask(businessObject)); for (const serviceTask of serviceTasks) { - const bounds = { - x: serviceTask.x, - y: serviceTask.y, - }; let deploymentModelUrl = serviceTask.businessObject.get('opentosca:deploymentModelUrl'); if (deploymentModelUrl.startsWith('{{ wineryEndpoint }}')) { deploymentModelUrl = deploymentModelUrl.replace('{{ wineryEndpoint }}', config.getWineryEndpoint()); @@ -54,17 +101,29 @@ export async function startOnDemandReplacementProcess(xml) { const serviceTask1 = modeling.appendShape(startEvent, { - type: 'bpmn:ServiceTask' + type: 'bpmn:ScriptTask', }, {x: 400, y: 200}); + serviceTask1.businessObject.set("scriptFormat", "javascript"); + serviceTask1.businessObject.set("script", createDeploymentScript( + { + opentoscaEndpoint: config.getOpenTOSCAEndpoint(), + csarName: "ondemand_" + (Math.random().toString().substring(3)), + deploymentModelUrl: deploymentModelUrl, + subprocessId: subProcess.id + } + )); const serviceTask2 = modeling.appendShape(serviceTask1, { type: 'bpmn:ServiceTask' }, {x: 600, y: 200}, subProcess); + + serviceTask2.businessObject.set("camunda:type", "external"); + serviceTask2.businessObject.set("camunda:topic", "fjhdhg"); } // layout diagram after successful transformation - let updated_xml = await getXml(modeler); - console.log(updated_xml); - return {status: 'transformed', xml: updated_xml}; + let updatedXml = await getXml(modeler); + console.log(updatedXml); + return updatedXml; } From a9bae65a0cb233306001c5e013eef1547a1ddace Mon Sep 17 00:00:00 2001 From: Christoph Walcher Date: Mon, 28 Aug 2023 21:36:21 +0200 Subject: [PATCH 6/8] fixup! Prototyp script task --- .../extensions/opentosca/replacement/OnDemandTransformator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/bpmn-q/modeler-component/extensions/opentosca/replacement/OnDemandTransformator.js b/components/bpmn-q/modeler-component/extensions/opentosca/replacement/OnDemandTransformator.js index 594a5fca..49c1a2b4 100644 --- a/components/bpmn-q/modeler-component/extensions/opentosca/replacement/OnDemandTransformator.js +++ b/components/bpmn-q/modeler-component/extensions/opentosca/replacement/OnDemandTransformator.js @@ -65,7 +65,7 @@ var buildPlans = JSON.parse(fetch('GET', buildPlansUrl)) var buildPlanUrl = buildPlans.plans[0]._links.self.href var createInstanceResponse = fetch('POST', buildPlanUrl + "/instances", JSON.stringify([])) -execution.setVariable(params.subprocessId + "_deploymentBuildPlanInstanceUrl", createInstanceResponse);`; +execution.setVariable(params.subprocessId + "_deploymentBuildPlanInstanceUrl", buildPlanUrl + "/instances/" + createInstanceResponse);`; } /** From 6557e96f565f7baf51fbb68ee0df8c90b5d5e3d9 Mon Sep 17 00:00:00 2001 From: Christoph Walcher Date: Mon, 11 Sep 2023 16:51:06 +0200 Subject: [PATCH 7/8] fix input parameter supplier --- .../opentosca/deployment/OpenTOSCAUtils.js | 2 +- .../replacement/OnDemandTransformator.js | 28 +++++++++++++------ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/components/bpmn-q/modeler-component/extensions/opentosca/deployment/OpenTOSCAUtils.js b/components/bpmn-q/modeler-component/extensions/opentosca/deployment/OpenTOSCAUtils.js index 7e57328e..32cfc4f1 100644 --- a/components/bpmn-q/modeler-component/extensions/opentosca/deployment/OpenTOSCAUtils.js +++ b/components/bpmn-q/modeler-component/extensions/opentosca/deployment/OpenTOSCAUtils.js @@ -224,7 +224,7 @@ export async function createServiceInstance(csar, camundaEngineEndpoint) { } -function makeId(length) { +export function makeId(length) { let result = ''; let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let charactersLength = characters.length; diff --git a/components/bpmn-q/modeler-component/extensions/opentosca/replacement/OnDemandTransformator.js b/components/bpmn-q/modeler-component/extensions/opentosca/replacement/OnDemandTransformator.js index 49c1a2b4..4aece5d6 100644 --- a/components/bpmn-q/modeler-component/extensions/opentosca/replacement/OnDemandTransformator.js +++ b/components/bpmn-q/modeler-component/extensions/opentosca/replacement/OnDemandTransformator.js @@ -10,17 +10,17 @@ */ import {createTempModelerFromXml} from '../../../editor/ModelerHandler'; -import { - getRootProcess, -} from '../../../editor/util/ModellingUtilities'; import {getXml} from '../../../editor/util/IoUtilities'; import {isDeployableServiceTask} from "../deployment/DeploymentUtils"; import * as config from "../framework-config/config-manager"; +import {makeId} from "../deployment/OpenTOSCAUtils"; +import {getCamundaEndpoint} from "../../../editor/config/EditorConfigManager"; function createDeploymentScript(params) { return ` var params = ${JSON.stringify(params)}; +params.csarName = "ondemand_" + (Math.random().toString().substring(3)); function fetch(method, url, body) { var resourceURL = new java.net.URL(url); @@ -63,8 +63,17 @@ var serviceTemplates = JSON.parse(fetch('GET', params.opentoscaEndpoint + "/" + var buildPlansUrl = serviceTemplates.service_templates[0]._links.self.href + '/buildplans' var buildPlans = JSON.parse(fetch('GET', buildPlansUrl)) var buildPlanUrl = buildPlans.plans[0]._links.self.href - -var createInstanceResponse = fetch('POST', buildPlanUrl + "/instances", JSON.stringify([])) +var inputParameters = JSON.parse(fetch('GET', buildPlanUrl)).input_parameters +for(var i = 0; i < inputParameters.length; i++) { + if(inputParameters[i].name === "camundaEndpoint") { + inputParameters[i].value = params.opentoscaEndpoint + } else if(inputParameters[i].name === "camundaTopic") { + inputParameters[i].value = params.camundaTopic + } else { + inputParameters[i].value = "null" + } +} +var createInstanceResponse = fetch('POST', buildPlanUrl + "/instances", JSON.stringify(inputParameters)) execution.setVariable(params.subprocessId + "_deploymentBuildPlanInstanceUrl", buildPlanUrl + "/instances/" + createInstanceResponse);`; } @@ -99,7 +108,7 @@ export async function startOnDemandReplacementProcess(xml) { type: 'bpmn:StartEvent' }, {x: 200, y: 200}, subProcess); - + let topicName = makeId(12); const serviceTask1 = modeling.appendShape(startEvent, { type: 'bpmn:ScriptTask', }, {x: 400, y: 200}); @@ -107,9 +116,10 @@ export async function startOnDemandReplacementProcess(xml) { serviceTask1.businessObject.set("script", createDeploymentScript( { opentoscaEndpoint: config.getOpenTOSCAEndpoint(), - csarName: "ondemand_" + (Math.random().toString().substring(3)), deploymentModelUrl: deploymentModelUrl, - subprocessId: subProcess.id + subprocessId: subProcess.id, + camundaTopic: topicName, + camundaEndpoint: getCamundaEndpoint() } )); @@ -119,7 +129,7 @@ export async function startOnDemandReplacementProcess(xml) { }, {x: 600, y: 200}, subProcess); serviceTask2.businessObject.set("camunda:type", "external"); - serviceTask2.businessObject.set("camunda:topic", "fjhdhg"); + serviceTask2.businessObject.set("camunda:topic", topicName); } // layout diagram after successful transformation From abfb5bf17c4a4ebaff335fea8e66596ea3a8950c Mon Sep 17 00:00:00 2001 From: Christoph Walcher Date: Mon, 11 Sep 2023 17:09:12 +0200 Subject: [PATCH 8/8] fix tests --- components/bpmn-q/test/tests/editor/plugin.spec.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/components/bpmn-q/test/tests/editor/plugin.spec.js b/components/bpmn-q/test/tests/editor/plugin.spec.js index b8ec76ca..412b178c 100644 --- a/components/bpmn-q/test/tests/editor/plugin.spec.js +++ b/components/bpmn-q/test/tests/editor/plugin.spec.js @@ -54,10 +54,6 @@ describe('Test plugins', function () { expect(extensions['quantme']).to.not.be.undefined; expect(extensions['opentosca']).to.not.be.undefined; expect(extensions['planqk']).to.not.be.undefined; - expect(transfButtons.length).to.equal(3); - expect(buttons.length).to.equal(3); - expect(tabs.length).to.equal(4); - expect(styles.length).to.equal(4); }); }); });