diff --git a/.gitignore b/.gitignore index c6cc0de..b8abc3a 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ lib/mvn-deps/ logs/ src_dataClasses/ src_wsproc/ +/.metadata/ diff --git a/MY-PRODUCT-NAME-product/README.md b/MY-PRODUCT-NAME-product/README.md deleted file mode 100644 index ee9062a..0000000 --- a/MY-PRODUCT-NAME-product/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# MY-PRODUCT-NAME - -YOUR DESCRIPTION GOES HERE - -## Demo - -YOUR DEMO DESCRIPTION GOES HERE - -## Setup - -YOUR SETUP DESCRIPTION GOES HERE - -``` -@variables.yaml@ -``` \ No newline at end of file diff --git a/README.md b/README.md index 0f94020..083112b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -# MY-PRODUCT-NAME +# Docker Connector -[![CI Build](https://github.com/axonivy-market/REPO-NAME/actions/workflows/ci.yml/badge.svg)](https://github.com/axonivy-market/REPO-NAME/actions/workflows/ci.yml) +[![CI Build](https://github.com/axonivy-market/docker-connector/actions/workflows/ci.yml/badge.svg)](https://github.com/axonivy-market/docker-connector/actions/workflows/ci.yml) -"YOUR SHORT DESCRIPTION GOES HERE" +Connector to create/start/stop/delete Docker containers -Read our [documentation](MY-PRODUCT-NAME-product/README.md). +Read our [documentation](docker-connector-product/README.md). diff --git a/docker-connector-demo/.classpath b/docker-connector-demo/.classpath new file mode 100644 index 0000000..aa20b3e --- /dev/null +++ b/docker-connector-demo/.classpath @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docker-connector-demo/.gitignore b/docker-connector-demo/.gitignore new file mode 100644 index 0000000..1b2547b --- /dev/null +++ b/docker-connector-demo/.gitignore @@ -0,0 +1,19 @@ +# general +Thumbs.db +.DS_Store +*~ +*.log + +# java +*.class +hs_err_pid* + +# maven +target/ +lib/mvn-deps/ + +# ivy +classes/ +src_dataClasses/ +src_wsproc/ +logs/ diff --git a/docker-connector-demo/.project b/docker-connector-demo/.project new file mode 100644 index 0000000..bbd4f3a --- /dev/null +++ b/docker-connector-demo/.project @@ -0,0 +1,49 @@ + + + docker-connector-demo + + + + + + ch.ivyteam.ivy.designer.dataClasses.ui.ivyDataClassBuilder + + + + + ch.ivyteam.ivy.designer.process.ui.ivyWebServiceProcessClassBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + ch.ivyteam.ivy.designer.ide.ivyModelValidationBuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + ch.ivyteam.ivy.project.IvyProjectNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.jem.beaninfo.BeanInfoNature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/docker-connector-demo/.settings/.jsdtscope b/docker-connector-demo/.settings/.jsdtscope new file mode 100644 index 0000000..cf5ec79 --- /dev/null +++ b/docker-connector-demo/.settings/.jsdtscope @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/docker-connector-demo/.settings/ch.ivyteam.ivy.designer.prefs b/docker-connector-demo/.settings/ch.ivyteam.ivy.designer.prefs new file mode 100644 index 0000000..227bf13 --- /dev/null +++ b/docker-connector-demo/.settings/ch.ivyteam.ivy.designer.prefs @@ -0,0 +1,5 @@ +ch.ivyteam.ivy.designer.preferences.DataClassPreferencePage\:DEFAULT_DATA_CLASS=com.axonivy.market.docker.connector.demo.Data +ch.ivyteam.ivy.designer.preferences.DataClassPreferencePage\:DEFAULT_NAMESPACE=com.axonivy.market.docker.connector.demo +ch.ivyteam.ivy.project.preferences\:PRIMEFACES_VERSION=11 +ch.ivyteam.ivy.project.preferences\:PROJECT_VERSION=100000 +eclipse.preferences.version=1 diff --git a/docker-connector-demo/.settings/org.eclipse.jdt.core.prefs b/docker-connector-demo/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..f78f7f7 --- /dev/null +++ b/docker-connector-demo/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,10 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/docker-connector-demo/.settings/org.eclipse.wst.common.component b/docker-connector-demo/.settings/org.eclipse.wst.common.component new file mode 100644 index 0000000..4b077bc --- /dev/null +++ b/docker-connector-demo/.settings/org.eclipse.wst.common.component @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/docker-connector-demo/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml b/docker-connector-demo/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml new file mode 100644 index 0000000..0d46547 --- /dev/null +++ b/docker-connector-demo/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/docker-connector-demo/.settings/org.eclipse.wst.common.project.facet.core.xml b/docker-connector-demo/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..c2098f9 --- /dev/null +++ b/docker-connector-demo/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/docker-connector-demo/.settings/org.eclipse.wst.css.core.prefs b/docker-connector-demo/.settings/org.eclipse.wst.css.core.prefs new file mode 100644 index 0000000..96b96cd --- /dev/null +++ b/docker-connector-demo/.settings/org.eclipse.wst.css.core.prefs @@ -0,0 +1,2 @@ +css-profile/=org.eclipse.wst.css.core.cssprofile.css3 +eclipse.preferences.version=1 diff --git a/docker-connector-demo/.settings/org.eclipse.wst.jsdt.ui.superType.container b/docker-connector-demo/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 0000000..3bd5d0a --- /dev/null +++ b/docker-connector-demo/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/docker-connector-demo/.settings/org.eclipse.wst.jsdt.ui.superType.name b/docker-connector-demo/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 0000000..05bd71b --- /dev/null +++ b/docker-connector-demo/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/docker-connector-demo/config/custom-fields.yaml b/docker-connector-demo/config/custom-fields.yaml new file mode 100644 index 0000000..aa19ae0 --- /dev/null +++ b/docker-connector-demo/config/custom-fields.yaml @@ -0,0 +1,20 @@ +# == Custom Fields Information == +# +# You can define here your project custom fields. +# Have a look at our documentation for more information. +# +CustomFields: +# Tasks: +# MyTaskCustomField: +# Label: My task custom field +# Description: This new task custom field can be used to ... +# Type: STRING +# Cases: +# MyCaseCustomField: +# Label: My case custom field +# Description: This new case custom field can be used to ... +# Type: STRING +# Starts: +# MyStartCustomField: +# Label: My start custom field +# Description: This new start custom field can be used to ... diff --git a/docker-connector-demo/config/databases.yaml b/docker-connector-demo/config/databases.yaml new file mode 100644 index 0000000..247b128 --- /dev/null +++ b/docker-connector-demo/config/databases.yaml @@ -0,0 +1 @@ +Databases: diff --git a/docker-connector-demo/config/overrides.any b/docker-connector-demo/config/overrides.any new file mode 100644 index 0000000..f59ec20 --- /dev/null +++ b/docker-connector-demo/config/overrides.any @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/docker-connector-demo/config/persistence.xml b/docker-connector-demo/config/persistence.xml new file mode 100644 index 0000000..d6b96d7 --- /dev/null +++ b/docker-connector-demo/config/persistence.xml @@ -0,0 +1,2 @@ + + diff --git a/docker-connector-demo/config/rest-clients.yaml b/docker-connector-demo/config/rest-clients.yaml new file mode 100644 index 0000000..8e85296 --- /dev/null +++ b/docker-connector-demo/config/rest-clients.yaml @@ -0,0 +1 @@ +RestClients: diff --git a/docker-connector-demo/config/roles.xml b/docker-connector-demo/config/roles.xml new file mode 100644 index 0000000..59892fe --- /dev/null +++ b/docker-connector-demo/config/roles.xml @@ -0,0 +1,4 @@ + + + Everybody + diff --git a/docker-connector-demo/config/users.xml b/docker-connector-demo/config/users.xml new file mode 100644 index 0000000..51a6906 --- /dev/null +++ b/docker-connector-demo/config/users.xml @@ -0,0 +1,2 @@ + + diff --git a/docker-connector-demo/config/variables.yaml b/docker-connector-demo/config/variables.yaml new file mode 100644 index 0000000..32ff8dd --- /dev/null +++ b/docker-connector-demo/config/variables.yaml @@ -0,0 +1,10 @@ +# == Variables == +# +# You can define here your project Variables. +# If you want to define/override a Variable for a specific Environment, +# add an additional ‘variables.yaml’ file in a subdirectory in the ‘Config’ folder: +# '/Config/_/variables.yaml +# +Variables: + AxonIvyEngine: + Port: 9090 \ No newline at end of file diff --git a/docker-connector-demo/config/webservice-clients.yaml b/docker-connector-demo/config/webservice-clients.yaml new file mode 100644 index 0000000..060b018 --- /dev/null +++ b/docker-connector-demo/config/webservice-clients.yaml @@ -0,0 +1 @@ +WebServiceClients: diff --git a/docker-connector-demo/dataclasses/com/axonivy/market/docker/connector/demo/Data.ivyClass b/docker-connector-demo/dataclasses/com/axonivy/market/docker/connector/demo/Data.ivyClass new file mode 100644 index 0000000..5fc0185 --- /dev/null +++ b/docker-connector-demo/dataclasses/com/axonivy/market/docker/connector/demo/Data.ivyClass @@ -0,0 +1,4 @@ +Data #class +com.axonivy.market.docker.connector.demo #namespace +containerId String #field +containerId PERSISTENT #fieldModifier diff --git a/docker-connector-demo/pom.xml b/docker-connector-demo/pom.xml new file mode 100644 index 0000000..94981f4 --- /dev/null +++ b/docker-connector-demo/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + com.axonivy.market + docker-connector-demo + 10.0.0-SNAPSHOT + iar + + Axon Ivy AG + + + + com.axonivy.market + docker-connector + 10.0.0-SNAPSHOT + iar + + + + + + com.axonivy.ivy.ci + project-build-plugin + 10.0.6 + true + + + + diff --git a/docker-connector-demo/processes/dockerDemo.p.json b/docker-connector-demo/processes/dockerDemo.p.json new file mode 100644 index 0000000..5f58bb7 --- /dev/null +++ b/docker-connector-demo/processes/dockerDemo.p.json @@ -0,0 +1,144 @@ +{ + "format" : "10.0.0", + "id" : "18A50F6DFF3B27D1", + "config" : { + "data" : "com.axonivy.market.docker.connector.demo.Data" + }, + "elements" : [ { + "id" : "f0", + "type" : "RequestStart", + "name" : "start.ivp", + "config" : { + "callSignature" : "start", + "outLink" : "start.ivp", + "tags" : "demo" + }, + "visual" : { + "at" : { "x" : 88, "y" : 296 } + }, + "connect" : { "id" : "f4", "to" : "f3" } + }, { + "id" : "f1", + "type" : "TaskEnd", + "visual" : { + "at" : { "x" : 968, "y" : 296 } + } + }, { + "id" : "f3", + "type" : "SubProcessCall", + "name" : "Create axonivy-engine container", + "config" : { + "call" : { + "params" : [ + { "name" : "image", "type" : "String" }, + { "name" : "name", "type" : "String" }, + { "name" : "ports", "type" : "List" } + ], + "map" : { + "param.image" : "\"axonivy/axonivy-engine:10.0\"", + "param.name" : "\"axonivy-engine\"" + }, + "code" : [ + "import com.axonivy.connector.docker.PortBinding;", + "PortBinding binding = new PortBinding();", + "binding.publicPort = ivy.var.AxonIvyEngine_Port.toNumber();", + "binding.internalPort = 8080;", + "", + "param.ports = [binding];" + ] + }, + "processCall" : "docker:createContainer(String,String,List)", + "output" : { + "map" : { + "out" : "in", + "out.containerId" : "result.containerId" + } + } + }, + "visual" : { + "at" : { "x" : 216, "y" : 296 }, + "icon" : "res:/webContent/icons/docker.png" + }, + "connect" : { "id" : "f6", "to" : "f5" } + }, { + "id" : "f5", + "type" : "SubProcessCall", + "name" : "Start Container", + "config" : { + "processCall" : "docker:startContainer(String)", + "call" : { + "params" : [ + { "name" : "containerId", "type" : "String" } + ], + "map" : { + "param.containerId" : "in.containerId" + } + } + }, + "visual" : { + "at" : { "x" : 360, "y" : 296 }, + "icon" : "res:/webContent/icons/docker.png" + }, + "connect" : { "id" : "f13", "to" : "f12" } + }, { + "id" : "f7", + "type" : "SubProcessCall", + "name" : "Stop Container", + "config" : { + "processCall" : "docker:stopContainer(String)", + "call" : { + "params" : [ + { "name" : "containerId", "type" : "String" } + ], + "map" : { + "param.containerId" : "in.containerId" + } + } + }, + "visual" : { + "at" : { "x" : 680, "y" : 296 }, + "icon" : "res:/webContent/icons/docker.png" + }, + "connect" : { "id" : "f10", "to" : "f9" } + }, { + "id" : "f9", + "type" : "SubProcessCall", + "name" : "Remove Container", + "config" : { + "processCall" : "docker:removeContainer(String)", + "call" : { + "params" : [ + { "name" : "containerId", "type" : "String" } + ], + "map" : { + "param.containerId" : "in.containerId" + } + } + }, + "visual" : { + "at" : { "x" : 840, "y" : 296 }, + "icon" : "res:/webContent/icons/docker.png" + }, + "connect" : { "id" : "f2", "to" : "f1" } + }, { + "id" : "f11", + "type" : "ProcessAnnotation", + "name" : "This demo creates a Docker container for the Docker image axonivy/axonivy-engine:10.0 then starts, stops and removes it.", + "visual" : { + "at" : { "x" : 211, "y" : 165 }, + "size" : { "width" : 274, "height" : 102 } + } + }, { + "id" : "f12", + "type" : "DialogCall", + "name" : "ShowEngine", + "config" : { + "dialogId" : "com.axonivy.market.docker.connector.demo.ShowEngine", + "startMethod" : "start()" + }, + "visual" : { + "at" : { "x" : 520, "y" : 296 } + }, + "connect" : { "id" : "f8", "to" : "f7" } + } ] +} \ No newline at end of file diff --git a/docker-connector-demo/src_hd/com/axonivy/market/docker/connector/demo/ShowEngine/ShowEngine.rddescriptor b/docker-connector-demo/src_hd/com/axonivy/market/docker/connector/demo/ShowEngine/ShowEngine.rddescriptor new file mode 100644 index 0000000..ae605f0 --- /dev/null +++ b/docker-connector-demo/src_hd/com/axonivy/market/docker/connector/demo/ShowEngine/ShowEngine.rddescriptor @@ -0,0 +1,7 @@ + + + + viewTechnology + JSF + + diff --git a/docker-connector-demo/src_hd/com/axonivy/market/docker/connector/demo/ShowEngine/ShowEngine.xhtml b/docker-connector-demo/src_hd/com/axonivy/market/docker/connector/demo/ShowEngine/ShowEngine.xhtml new file mode 100644 index 0000000..bdfcfab --- /dev/null +++ b/docker-connector-demo/src_hd/com/axonivy/market/docker/connector/demo/ShowEngine/ShowEngine.xhtml @@ -0,0 +1,28 @@ + + + + Show Engine + + +

+ Axon Ivy Engine running in a container +

+ + + + +
+
+ + +
+
+ +
+
+
+ + \ No newline at end of file diff --git a/docker-connector-demo/src_hd/com/axonivy/market/docker/connector/demo/ShowEngine/ShowEngineData.ivyClass b/docker-connector-demo/src_hd/com/axonivy/market/docker/connector/demo/ShowEngine/ShowEngineData.ivyClass new file mode 100644 index 0000000..1ac74f4 --- /dev/null +++ b/docker-connector-demo/src_hd/com/axonivy/market/docker/connector/demo/ShowEngine/ShowEngineData.ivyClass @@ -0,0 +1,2 @@ +ShowEngineData #class +com.axonivy.market.docker.connector.demo.ShowEngine #namespace diff --git a/docker-connector-demo/src_hd/com/axonivy/market/docker/connector/demo/ShowEngine/ShowEngineProcess.p.json b/docker-connector-demo/src_hd/com/axonivy/market/docker/connector/demo/ShowEngine/ShowEngineProcess.p.json new file mode 100644 index 0000000..b91d45a --- /dev/null +++ b/docker-connector-demo/src_hd/com/axonivy/market/docker/connector/demo/ShowEngine/ShowEngineProcess.p.json @@ -0,0 +1,44 @@ +{ + "format" : "10.0.0", + "id" : "18A510557E128639", + "kind" : "HTML_DIALOG", + "config" : { + "data" : "com.axonivy.market.docker.connector.demo.ShowEngine.ShowEngineData" + }, + "elements" : [ { + "id" : "f0", + "type" : "HtmlDialogStart", + "name" : "start()", + "config" : { + "callSignature" : "start", + "guid" : "18A510557E2EC92A" + }, + "visual" : { + "at" : { "x" : 96, "y" : 64 } + }, + "connect" : { "id" : "f2", "to" : "f1" } + }, { + "id" : "f1", + "type" : "HtmlDialogEnd", + "visual" : { + "at" : { "x" : 224, "y" : 64 } + } + }, { + "id" : "f3", + "type" : "HtmlDialogEventStart", + "name" : "close", + "config" : { + "guid" : "18A510557E378E4D" + }, + "visual" : { + "at" : { "x" : 96, "y" : 160 } + }, + "connect" : { "id" : "f5", "to" : "f4" } + }, { + "id" : "f4", + "type" : "HtmlDialogExit", + "visual" : { + "at" : { "x" : 224, "y" : 160 } + } + } ] +} \ No newline at end of file diff --git a/docker-connector-demo/webContent/layouts/frame-10-full-width.xhtml b/docker-connector-demo/webContent/layouts/frame-10-full-width.xhtml new file mode 100644 index 0000000..06f02b6 --- /dev/null +++ b/docker-connector-demo/webContent/layouts/frame-10-full-width.xhtml @@ -0,0 +1,60 @@ + + + + + + + + + + <ui:insert name="title">Ivy Html Dialog</ui:insert> + + + + + + + + + +
+ + default content + +
+ + + + + + + +
+ \ No newline at end of file diff --git a/docker-connector-demo/webContent/layouts/includes/exception-details.xhtml b/docker-connector-demo/webContent/layouts/includes/exception-details.xhtml new file mode 100644 index 0000000..bbc3cce --- /dev/null +++ b/docker-connector-demo/webContent/layouts/includes/exception-details.xhtml @@ -0,0 +1,109 @@ + + + + + + +

+ +

+ + +

Error id

+

#{errorPage.exceptionId}

+

Error Timestamp

+

#{errorPage.createdAt}

+
+ + + + +

Attributes

+
+ + + + + + + + + + + + + + + +
NameValue
+
+
+

Thrown by

+

Process: + +
Element: + +

+
+ + +

Process call stack

+ +
#{caller.callerElement}
+
+
+ +

Technical cause

+
#{causedBy.class.simpleName}: #{causedBy.message.trim()}
+
+
+ +

Request Uri

+

#{errorPage.getRequestUri()}

+
+

Servlet

+

#{errorPage.getServletName()}

+
+ +

Application

+

#{errorPage.applicationName}

+
+ + +

Thread local values

+
+ + + + + + + + + + + + + + + +
KeyValue
+
+
+
+ +

Stack-Trace

+
#{errorPage.getStackTrace()}
+
+ diff --git a/docker-connector-demo/webContent/layouts/includes/exception.xhtml b/docker-connector-demo/webContent/layouts/includes/exception.xhtml new file mode 100644 index 0000000..1b255a2 --- /dev/null +++ b/docker-connector-demo/webContent/layouts/includes/exception.xhtml @@ -0,0 +1,47 @@ + + + + + + + + + +
+
+ + +
+ + + + + + + + + +
+ + \ No newline at end of file diff --git a/docker-connector-demo/webContent/layouts/includes/footer.xhtml b/docker-connector-demo/webContent/layouts/includes/footer.xhtml new file mode 100644 index 0000000..f21699e --- /dev/null +++ b/docker-connector-demo/webContent/layouts/includes/footer.xhtml @@ -0,0 +1,18 @@ + + + +
+ + #{ivyAdvisor.applicationName} + + +
+
+ + \ No newline at end of file diff --git a/docker-connector-demo/webContent/layouts/includes/progress-loader.xhtml b/docker-connector-demo/webContent/layouts/includes/progress-loader.xhtml new file mode 100644 index 0000000..0d68a75 --- /dev/null +++ b/docker-connector-demo/webContent/layouts/includes/progress-loader.xhtml @@ -0,0 +1,15 @@ + + + + +
+
+
Loading...
+
+
+ + + +
+
\ No newline at end of file diff --git a/docker-connector-product/README.md b/docker-connector-product/README.md new file mode 100644 index 0000000..30aed7d --- /dev/null +++ b/docker-connector-product/README.md @@ -0,0 +1,16 @@ +# Docker Connector + +Create, start, stop, remove Docker containers with the Axon Ivy's Docker Connector directly from your business processes. + +## Demo + +The demo process creates and starts an additional Axon Ivy Engine in a Docker container. +Then the process shows a HTML Dialog where you can open an additional browser tab that shows the info page of the Axon Ivy Engine. +If you proceed in the HTML Dialog, the container gets stopped and removed. + +## Setup + +To setup the Docker Connnector, add the following variable to your Axon Ivy Project: +``` +@variables.yaml@ +``` diff --git a/MY-PRODUCT-NAME-product/pom.xml b/docker-connector-product/pom.xml similarity index 94% rename from MY-PRODUCT-NAME-product/pom.xml rename to docker-connector-product/pom.xml index dd59011..f7fd1d7 100644 --- a/MY-PRODUCT-NAME-product/pom.xml +++ b/docker-connector-product/pom.xml @@ -1,12 +1,12 @@ 4.0.0 com.axonivy.market - MY-PRODUCT-NAME-product + docker-connector-product 10.0.0-SNAPSHOT pom - ../MY-PRODUCT-NAME/config/variables.yaml + ../docker-connector/config/variables.yaml diff --git a/MY-PRODUCT-NAME-product/product.json b/docker-connector-product/product.json similarity index 58% rename from MY-PRODUCT-NAME-product/product.json rename to docker-connector-product/product.json index a5a4b33..662691b 100644 --- a/MY-PRODUCT-NAME-product/product.json +++ b/docker-connector-product/product.json @@ -6,8 +6,8 @@ "data": { "projects": [ { - "groupId": "MY-GROUP-ID", - "artifactId": "MY-PRODUCT-NAME-demo", + "groupId": "com.axonivy.market", + "artifactId": "docker-connector-demo", "version": "${version}", "type": "iar" } @@ -28,8 +28,8 @@ "data": { "dependencies": [ { - "groupId": "MY-GROUP-ID", - "artifactId": "MY-PRODUCT-NAME", + "groupId": "com.axonivy.market", + "artifactId": "docker-connector", "version": "${version}", "type": "iar" } @@ -44,27 +44,6 @@ } ] } - }, - { - "id": "maven-dropins", - "data": { - "dependencies": [ - { - "groupId": "MY-GROUP-ID", - "artifactId": "MY-PRODUCT-NAME", - "version": "${version}" - } - ], - "repositories": [ - { - "id": "maven.axonivy.com", - "url": "https://maven.axonivy.com", - "snapshots": { - "enabled": "true" - } - } - ] - } } ] } diff --git a/MY-PRODUCT-NAME-product/zip.xml b/docker-connector-product/zip.xml similarity index 100% rename from MY-PRODUCT-NAME-product/zip.xml rename to docker-connector-product/zip.xml diff --git a/docker-connector-test/.classpath b/docker-connector-test/.classpath new file mode 100644 index 0000000..8a52195 --- /dev/null +++ b/docker-connector-test/.classpath @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docker-connector-test/.gitignore b/docker-connector-test/.gitignore new file mode 100644 index 0000000..1b2547b --- /dev/null +++ b/docker-connector-test/.gitignore @@ -0,0 +1,19 @@ +# general +Thumbs.db +.DS_Store +*~ +*.log + +# java +*.class +hs_err_pid* + +# maven +target/ +lib/mvn-deps/ + +# ivy +classes/ +src_dataClasses/ +src_wsproc/ +logs/ diff --git a/docker-connector-test/.project b/docker-connector-test/.project new file mode 100644 index 0000000..f560f36 --- /dev/null +++ b/docker-connector-test/.project @@ -0,0 +1,49 @@ + + + docker-connector-test + + + + + + ch.ivyteam.ivy.designer.dataClasses.ui.ivyDataClassBuilder + + + + + ch.ivyteam.ivy.designer.process.ui.ivyWebServiceProcessClassBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + ch.ivyteam.ivy.designer.ide.ivyModelValidationBuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + ch.ivyteam.ivy.project.IvyProjectNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.jem.beaninfo.BeanInfoNature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/docker-connector-test/.settings/.jsdtscope b/docker-connector-test/.settings/.jsdtscope new file mode 100644 index 0000000..cf5ec79 --- /dev/null +++ b/docker-connector-test/.settings/.jsdtscope @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/docker-connector-test/.settings/ch.ivyteam.ivy.designer.prefs b/docker-connector-test/.settings/ch.ivyteam.ivy.designer.prefs new file mode 100644 index 0000000..552c153 --- /dev/null +++ b/docker-connector-test/.settings/ch.ivyteam.ivy.designer.prefs @@ -0,0 +1,5 @@ +ch.ivyteam.ivy.designer.preferences.DataClassPreferencePage\:DEFAULT_DATA_CLASS=com.axonivy.market.docker.connector.test.Data +ch.ivyteam.ivy.designer.preferences.DataClassPreferencePage\:DEFAULT_NAMESPACE=com.axonivy.market.docker.connector.test +ch.ivyteam.ivy.project.preferences\:PRIMEFACES_VERSION=11 +ch.ivyteam.ivy.project.preferences\:PROJECT_VERSION=100000 +eclipse.preferences.version=1 diff --git a/docker-connector-test/.settings/org.eclipse.jdt.core.prefs b/docker-connector-test/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..f78f7f7 --- /dev/null +++ b/docker-connector-test/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,10 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/docker-connector-test/.settings/org.eclipse.wst.common.component b/docker-connector-test/.settings/org.eclipse.wst.common.component new file mode 100644 index 0000000..31ae991 --- /dev/null +++ b/docker-connector-test/.settings/org.eclipse.wst.common.component @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/docker-connector-test/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml b/docker-connector-test/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml new file mode 100644 index 0000000..0d46547 --- /dev/null +++ b/docker-connector-test/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/docker-connector-test/.settings/org.eclipse.wst.common.project.facet.core.xml b/docker-connector-test/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..c2098f9 --- /dev/null +++ b/docker-connector-test/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/docker-connector-test/.settings/org.eclipse.wst.css.core.prefs b/docker-connector-test/.settings/org.eclipse.wst.css.core.prefs new file mode 100644 index 0000000..96b96cd --- /dev/null +++ b/docker-connector-test/.settings/org.eclipse.wst.css.core.prefs @@ -0,0 +1,2 @@ +css-profile/=org.eclipse.wst.css.core.cssprofile.css3 +eclipse.preferences.version=1 diff --git a/docker-connector-test/.settings/org.eclipse.wst.jsdt.ui.superType.container b/docker-connector-test/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 0000000..3bd5d0a --- /dev/null +++ b/docker-connector-test/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/docker-connector-test/.settings/org.eclipse.wst.jsdt.ui.superType.name b/docker-connector-test/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 0000000..05bd71b --- /dev/null +++ b/docker-connector-test/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/docker-connector-test/config/custom-fields.yaml b/docker-connector-test/config/custom-fields.yaml new file mode 100644 index 0000000..aa19ae0 --- /dev/null +++ b/docker-connector-test/config/custom-fields.yaml @@ -0,0 +1,20 @@ +# == Custom Fields Information == +# +# You can define here your project custom fields. +# Have a look at our documentation for more information. +# +CustomFields: +# Tasks: +# MyTaskCustomField: +# Label: My task custom field +# Description: This new task custom field can be used to ... +# Type: STRING +# Cases: +# MyCaseCustomField: +# Label: My case custom field +# Description: This new case custom field can be used to ... +# Type: STRING +# Starts: +# MyStartCustomField: +# Label: My start custom field +# Description: This new start custom field can be used to ... diff --git a/docker-connector-test/config/databases.yaml b/docker-connector-test/config/databases.yaml new file mode 100644 index 0000000..247b128 --- /dev/null +++ b/docker-connector-test/config/databases.yaml @@ -0,0 +1 @@ +Databases: diff --git a/docker-connector-test/config/overrides.any b/docker-connector-test/config/overrides.any new file mode 100644 index 0000000..f59ec20 --- /dev/null +++ b/docker-connector-test/config/overrides.any @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/docker-connector-test/config/persistence.xml b/docker-connector-test/config/persistence.xml new file mode 100644 index 0000000..d6b96d7 --- /dev/null +++ b/docker-connector-test/config/persistence.xml @@ -0,0 +1,2 @@ + + diff --git a/docker-connector-test/config/rest-clients.yaml b/docker-connector-test/config/rest-clients.yaml new file mode 100644 index 0000000..8e85296 --- /dev/null +++ b/docker-connector-test/config/rest-clients.yaml @@ -0,0 +1 @@ +RestClients: diff --git a/docker-connector-test/config/roles.xml b/docker-connector-test/config/roles.xml new file mode 100644 index 0000000..59892fe --- /dev/null +++ b/docker-connector-test/config/roles.xml @@ -0,0 +1,4 @@ + + + Everybody + diff --git a/docker-connector-test/config/users.xml b/docker-connector-test/config/users.xml new file mode 100644 index 0000000..51a6906 --- /dev/null +++ b/docker-connector-test/config/users.xml @@ -0,0 +1,2 @@ + + diff --git a/docker-connector-test/config/variables.yaml b/docker-connector-test/config/variables.yaml new file mode 100644 index 0000000..d9ce3d6 --- /dev/null +++ b/docker-connector-test/config/variables.yaml @@ -0,0 +1,8 @@ +# == Variables == +# +# You can define here your project Variables. +# If you want to define/override a Variable for a specific Environment, +# add an additional ‘variables.yaml’ file in a subdirectory in the ‘Config’ folder: +# '/Config/_/variables.yaml +# +Variables: diff --git a/docker-connector-test/config/webservice-clients.yaml b/docker-connector-test/config/webservice-clients.yaml new file mode 100644 index 0000000..060b018 --- /dev/null +++ b/docker-connector-test/config/webservice-clients.yaml @@ -0,0 +1 @@ +WebServiceClients: diff --git a/docker-connector-test/dataclasses/com/axonivy/market/docker/connector/test/Data.ivyClass b/docker-connector-test/dataclasses/com/axonivy/market/docker/connector/test/Data.ivyClass new file mode 100644 index 0000000..c671fce --- /dev/null +++ b/docker-connector-test/dataclasses/com/axonivy/market/docker/connector/test/Data.ivyClass @@ -0,0 +1,2 @@ +Data #class +com.axonivy.market.docker.connector.test #namespace diff --git a/docker-connector-test/pom.xml b/docker-connector-test/pom.xml new file mode 100644 index 0000000..ff67f7d --- /dev/null +++ b/docker-connector-test/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + com.axonivy.market + docker-connector-test + 10.0.0-SNAPSHOT + iar-integration-test + + Axon Ivy AG + + + + com.axonivy.market + docker-connector-demo + ${project.version} + iar + + + com.axonivy.ivy.webtest + web-tester + 10.0.0 + test + + + + src_test + + + com.axonivy.ivy.ci + project-build-plugin + 10.0.6 + true + + + + diff --git a/docker-connector-test/src_test/com/axonivy/market/docker/connector/test/ITDockerConnector.java b/docker-connector-test/src_test/com/axonivy/market/docker/connector/test/ITDockerConnector.java new file mode 100644 index 0000000..7ece8e2 --- /dev/null +++ b/docker-connector-test/src_test/com/axonivy/market/docker/connector/test/ITDockerConnector.java @@ -0,0 +1,42 @@ +package com.axonivy.market.docker.connector.test; + +import static com.codeborne.selenide.Selenide.$; +import static com.codeborne.selenide.Selenide.open; +import static org.assertj.core.api.Assertions.assertThat; +import java.time.Duration; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriverException; +import com.axonivy.ivy.webtest.IvyWebTest; +import com.axonivy.ivy.webtest.engine.EngineUrl; +import com.codeborne.selenide.Selenide; + +@IvyWebTest +public class ITDockerConnector { + + @Test + public void demo() { + open(EngineUrl.createProcessUrl("docker-connector-demo/18A50F6DFF3B27D1/start.ivp")); + + // Open link to started engine + $(By.id("form:OpenEngine")).click(); + + + Selenide.Wait() + .withTimeout(Duration.ofMinutes(1)) + .pollingEvery(Duration.ofSeconds(5)) + .ignoring(WebDriverException.class) + .ignoring(AssertionError.class) + .until(driver -> { + Selenide.switchTo().window(1); + Selenide.refresh(); + assertThat(Selenide.title()).contains("Axon Ivy Engine"); + return true; + }); + + Selenide.switchTo().window(0); + + $(By.id("form:proceed")).click(); + } + +} \ No newline at end of file diff --git a/docker-connector/.classpath b/docker-connector/.classpath new file mode 100644 index 0000000..aa20b3e --- /dev/null +++ b/docker-connector/.classpath @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docker-connector/.gitignore b/docker-connector/.gitignore new file mode 100644 index 0000000..1b2547b --- /dev/null +++ b/docker-connector/.gitignore @@ -0,0 +1,19 @@ +# general +Thumbs.db +.DS_Store +*~ +*.log + +# java +*.class +hs_err_pid* + +# maven +target/ +lib/mvn-deps/ + +# ivy +classes/ +src_dataClasses/ +src_wsproc/ +logs/ diff --git a/docker-connector/.project b/docker-connector/.project new file mode 100644 index 0000000..a3551fe --- /dev/null +++ b/docker-connector/.project @@ -0,0 +1,49 @@ + + + docker-connector + + + + + + ch.ivyteam.ivy.designer.dataClasses.ui.ivyDataClassBuilder + + + + + ch.ivyteam.ivy.designer.process.ui.ivyWebServiceProcessClassBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + ch.ivyteam.ivy.designer.ide.ivyModelValidationBuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + ch.ivyteam.ivy.project.IvyProjectNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.jem.beaninfo.BeanInfoNature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/docker-connector/.settings/.jsdtscope b/docker-connector/.settings/.jsdtscope new file mode 100644 index 0000000..cf5ec79 --- /dev/null +++ b/docker-connector/.settings/.jsdtscope @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/docker-connector/.settings/ch.ivyteam.ivy.designer.prefs b/docker-connector/.settings/ch.ivyteam.ivy.designer.prefs new file mode 100644 index 0000000..95170c5 --- /dev/null +++ b/docker-connector/.settings/ch.ivyteam.ivy.designer.prefs @@ -0,0 +1,5 @@ +ch.ivyteam.ivy.designer.preferences.DataClassPreferencePage\:DEFAULT_DATA_CLASS=docker.connector.Data +ch.ivyteam.ivy.designer.preferences.DataClassPreferencePage\:DEFAULT_NAMESPACE=docker.connector +ch.ivyteam.ivy.project.preferences\:PRIMEFACES_VERSION=11 +ch.ivyteam.ivy.project.preferences\:PROJECT_VERSION=100000 +eclipse.preferences.version=1 diff --git a/docker-connector/.settings/org.eclipse.jdt.core.prefs b/docker-connector/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..f78f7f7 --- /dev/null +++ b/docker-connector/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,10 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/docker-connector/.settings/org.eclipse.wst.common.component b/docker-connector/.settings/org.eclipse.wst.common.component new file mode 100644 index 0000000..cd7037c --- /dev/null +++ b/docker-connector/.settings/org.eclipse.wst.common.component @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/docker-connector/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml b/docker-connector/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml new file mode 100644 index 0000000..0d46547 --- /dev/null +++ b/docker-connector/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/docker-connector/.settings/org.eclipse.wst.common.project.facet.core.xml b/docker-connector/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..c2098f9 --- /dev/null +++ b/docker-connector/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/docker-connector/.settings/org.eclipse.wst.css.core.prefs b/docker-connector/.settings/org.eclipse.wst.css.core.prefs new file mode 100644 index 0000000..96b96cd --- /dev/null +++ b/docker-connector/.settings/org.eclipse.wst.css.core.prefs @@ -0,0 +1,2 @@ +css-profile/=org.eclipse.wst.css.core.cssprofile.css3 +eclipse.preferences.version=1 diff --git a/docker-connector/.settings/org.eclipse.wst.jsdt.ui.superType.container b/docker-connector/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 0000000..3bd5d0a --- /dev/null +++ b/docker-connector/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/docker-connector/.settings/org.eclipse.wst.jsdt.ui.superType.name b/docker-connector/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 0000000..05bd71b --- /dev/null +++ b/docker-connector/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/docker-connector/config/custom-fields.yaml b/docker-connector/config/custom-fields.yaml new file mode 100644 index 0000000..aa19ae0 --- /dev/null +++ b/docker-connector/config/custom-fields.yaml @@ -0,0 +1,20 @@ +# == Custom Fields Information == +# +# You can define here your project custom fields. +# Have a look at our documentation for more information. +# +CustomFields: +# Tasks: +# MyTaskCustomField: +# Label: My task custom field +# Description: This new task custom field can be used to ... +# Type: STRING +# Cases: +# MyCaseCustomField: +# Label: My case custom field +# Description: This new case custom field can be used to ... +# Type: STRING +# Starts: +# MyStartCustomField: +# Label: My start custom field +# Description: This new start custom field can be used to ... diff --git a/docker-connector/config/databases.yaml b/docker-connector/config/databases.yaml new file mode 100644 index 0000000..247b128 --- /dev/null +++ b/docker-connector/config/databases.yaml @@ -0,0 +1 @@ +Databases: diff --git a/docker-connector/config/overrides.any b/docker-connector/config/overrides.any new file mode 100644 index 0000000..f59ec20 --- /dev/null +++ b/docker-connector/config/overrides.any @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/docker-connector/config/persistence.xml b/docker-connector/config/persistence.xml new file mode 100644 index 0000000..d6b96d7 --- /dev/null +++ b/docker-connector/config/persistence.xml @@ -0,0 +1,2 @@ + + diff --git a/docker-connector/config/rest-clients.yaml b/docker-connector/config/rest-clients.yaml new file mode 100644 index 0000000..8e85296 --- /dev/null +++ b/docker-connector/config/rest-clients.yaml @@ -0,0 +1 @@ +RestClients: diff --git a/docker-connector/config/roles.xml b/docker-connector/config/roles.xml new file mode 100644 index 0000000..59892fe --- /dev/null +++ b/docker-connector/config/roles.xml @@ -0,0 +1,4 @@ + + + Everybody + diff --git a/docker-connector/config/users.xml b/docker-connector/config/users.xml new file mode 100644 index 0000000..51a6906 --- /dev/null +++ b/docker-connector/config/users.xml @@ -0,0 +1,2 @@ + + diff --git a/docker-connector/config/variables.yaml b/docker-connector/config/variables.yaml new file mode 100644 index 0000000..e660760 --- /dev/null +++ b/docker-connector/config/variables.yaml @@ -0,0 +1,25 @@ +# == Variables == +# +# You can define here your project Variables. +# If you want to define/override a Variable for a specific Environment, +# add an additional ‘variables.yaml’ file in a subdirectory in the ‘Config’ folder: +# '/Config/_/variables.yaml +# +Variables: + Docker: + # URL to communicate with the docker daemon + # Windows Docker Desktop [https://www.docker.com/products/docker-desktop/] (localhost only): + # npipe:////./pipe/dockerDesktopLinuxEngine + # + # Windows Podman [https://podman.io] (localhost only): + # npipe:////./pipe/docker_engine + # + # Linux (localhost only): + # unix:///var/run/docker.sock + # + # TCP (Outside container): + # tcp://localhost:2375 + # + # TCP (Inside a container): + # tcp://host.docker.internal:2375 + URL: "unix:///var/run/docker.sock" \ No newline at end of file diff --git a/docker-connector/config/webservice-clients.yaml b/docker-connector/config/webservice-clients.yaml new file mode 100644 index 0000000..060b018 --- /dev/null +++ b/docker-connector/config/webservice-clients.yaml @@ -0,0 +1 @@ +WebServiceClients: diff --git a/docker-connector/dataclasses/com/axonivy/connector/docker/Data.ivyClass b/docker-connector/dataclasses/com/axonivy/connector/docker/Data.ivyClass new file mode 100644 index 0000000..814e1ef --- /dev/null +++ b/docker-connector/dataclasses/com/axonivy/connector/docker/Data.ivyClass @@ -0,0 +1,10 @@ +Data #class +com.axonivy.connector.docker #namespace +image String #field +image PERSISTENT #fieldModifier +ports List #field +ports PERSISTENT #fieldModifier +containerId String #field +containerId PERSISTENT #fieldModifier +name String #field +name PERSISTENT #fieldModifier diff --git a/docker-connector/dataclasses/com/axonivy/connector/docker/PortBinding.ivyClass b/docker-connector/dataclasses/com/axonivy/connector/docker/PortBinding.ivyClass new file mode 100644 index 0000000..e3e591c --- /dev/null +++ b/docker-connector/dataclasses/com/axonivy/connector/docker/PortBinding.ivyClass @@ -0,0 +1,6 @@ +PortBinding #class +com.axonivy.connector.docker #namespace +publicPort Number #field +publicPort PERSISTENT #fieldModifier +internalPort Number #field +internalPort PERSISTENT #fieldModifier diff --git a/docker-connector/dataclasses/docker/connector/Data.ivyClass b/docker-connector/dataclasses/docker/connector/Data.ivyClass new file mode 100644 index 0000000..caff849 --- /dev/null +++ b/docker-connector/dataclasses/docker/connector/Data.ivyClass @@ -0,0 +1,2 @@ +Data #class +docker.connector #namespace diff --git a/docker-connector/pom.xml b/docker-connector/pom.xml new file mode 100644 index 0000000..4624a24 --- /dev/null +++ b/docker-connector/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + com.axonivy.market + docker-connector + 10.0.0-SNAPSHOT + iar + + Axon Ivy AG + + + + com.github.docker-java + docker-java-core + 3.3.3 + + + com.google.guava + guava + + + + + com.github.docker-java + docker-java-transport-httpclient5 + 3.3.3 + + + + + + com.axonivy.ivy.ci + project-build-plugin + 10.0.6 + true + + + + diff --git a/docker-connector/processes/docker.p.json b/docker-connector/processes/docker.p.json new file mode 100644 index 0000000..9b206ad --- /dev/null +++ b/docker-connector/processes/docker.p.json @@ -0,0 +1,217 @@ +{ + "format" : "10.0.0", + "id" : "18A50DF32C4DF1E5", + "kind" : "CALLABLE_SUB", + "config" : { + "data" : "com.axonivy.connector.docker.Data" + }, + "elements" : [ { + "id" : "f0", + "type" : "CallSubStart", + "name" : "createContainer(String,String,List)", + "config" : { + "callSignature" : "createContainer", + "input" : { + "params" : [ + { "name" : "image", "type" : "String" }, + { "name" : "name", "type" : "String" }, + { "name" : "ports", "type" : "List" } + ], + "map" : { + "out.image" : "param.image", + "out.name" : "param.name", + "out.ports" : "param.ports" + } + }, + "result" : { + "params" : [ + { "name" : "containerId", "type" : "String" } + ], + "map" : { + "result.containerId" : "in.containerId" + } + }, + "tags" : "connector" + }, + "visual" : { + "at" : { "x" : 176, "y" : 72 }, + "icon" : "res:/webContent/icons/docker.png?small" + }, + "connect" : { "id" : "f4", "to" : "f3" } + }, { + "id" : "f1", + "type" : "CallSubEnd", + "visual" : { + "at" : { "x" : 504, "y" : 72 } + } + }, { + "id" : "f3", + "type" : "Script", + "name" : "Create Container", + "config" : { + "output" : { + "code" : [ + "import com.github.dockerjava.api.model.Ports.Binding;", + "import com.github.dockerjava.api.model.ExposedPort;", + "import com.github.dockerjava.api.command.CreateContainerResponse;", + "import com.github.dockerjava.api.model.HostConfig;", + "import com.github.dockerjava.api.model.PortBinding;", + "import com.axonivy.connector.docker.IvyDockerClient;", + "", + "Binding.bindPort(15);", + "List ports = [];", + "for (com.axonivy.connector.docker.PortBinding binding : in.ports) { ", + " Binding b = Binding.bindPort(binding.publicPort);", + " ports.add(new PortBinding(b, new ExposedPort(binding.internalPort)));", + "}", + "HostConfig hostConfig = HostConfig.newHostConfig();", + "if (! ports.isEmpty()) {", + " hostConfig.withPortBindings(ports);", + "}", + "CreateContainerResponse response = IvyDockerClient.instance()", + " .createContainerCmd(in.image)", + " .withName(in.name)", + " .withHostConfig(hostConfig)", + " .exec();", + "out.containerId = response.id;" + ] + } + }, + "visual" : { + "at" : { "x" : 360, "y" : 72 } + }, + "connect" : { "id" : "f2", "to" : "f1" } + }, { + "id" : "f5", + "type" : "CallSubStart", + "name" : "startContainer(String)", + "config" : { + "callSignature" : "startContainer", + "input" : { + "params" : [ + { "name" : "containerId", "type" : "String" } + ], + "map" : { + "out.containerId" : "param.containerId" + } + }, + "tags" : "connector" + }, + "visual" : { + "at" : { "x" : 176, "y" : 184 }, + "icon" : "res:/webContent/icons/docker.png?small" + }, + "connect" : { "id" : "f8", "to" : "f7" } + }, { + "id" : "f6", + "type" : "CallSubEnd", + "visual" : { + "at" : { "x" : 512, "y" : 184 } + } + }, { + "id" : "f7", + "type" : "Script", + "name" : "Start Container", + "config" : { + "output" : { + "code" : [ + "import com.axonivy.connector.docker.IvyDockerClient;", + "", + "IvyDockerClient.instance().startContainer(in.containerId);" + ] + } + }, + "visual" : { + "at" : { "x" : 368, "y" : 184 } + }, + "connect" : { "id" : "f9", "to" : "f6" } + }, { + "id" : "f10", + "type" : "CallSubStart", + "name" : "stopContainer(String)", + "config" : { + "callSignature" : "stopContainer", + "input" : { + "params" : [ + { "name" : "containerId", "type" : "String" } + ], + "map" : { + "out.containerId" : "param.containerId" + } + }, + "tags" : "connector" + }, + "visual" : { + "at" : { "x" : 176, "y" : 288 }, + "icon" : "res:/webContent/icons/docker.png?small" + }, + "connect" : { "id" : "f14", "to" : "f12" } + }, { + "id" : "f11", + "type" : "CallSubEnd", + "visual" : { + "at" : { "x" : 512, "y" : 288 } + } + }, { + "id" : "f12", + "type" : "Script", + "name" : "Stop Container", + "config" : { + "output" : { + "code" : [ + "import com.axonivy.connector.docker.IvyDockerClient;", + "", + "IvyDockerClient.instance().stopContainer(in.containerId);" + ] + } + }, + "visual" : { + "at" : { "x" : 368, "y" : 288 } + }, + "connect" : { "id" : "f13", "to" : "f11" } + }, { + "id" : "f15", + "type" : "CallSubStart", + "name" : "removeContainer", + "config" : { + "callSignature" : "removeContainer", + "input" : { + "params" : [ + { "name" : "containerId", "type" : "String" } + ], + "map" : { + "out.containerId" : "param.containerId" + } + }, + "tags" : "connector" + }, + "visual" : { + "at" : { "x" : 184, "y" : 408 }, + "icon" : "res:/webContent/icons/docker.png?small" + }, + "connect" : { "id" : "f18", "to" : "f17" } + }, { + "id" : "f16", + "type" : "CallSubEnd", + "visual" : { + "at" : { "x" : 520, "y" : 408 } + } + }, { + "id" : "f17", + "type" : "Script", + "name" : "Remove Container", + "config" : { + "output" : { + "code" : [ + "import com.axonivy.connector.docker.IvyDockerClient;", + "", + "IvyDockerClient.instance().removeContainer(in.containerId);" + ] + } + }, + "visual" : { + "at" : { "x" : 376, "y" : 408 } + }, + "connect" : { "id" : "f19", "to" : "f16" } + } ] +} \ No newline at end of file diff --git a/docker-connector/src/com/axonivy/connector/docker/AbstractResultCallback.java b/docker-connector/src/com/axonivy/connector/docker/AbstractResultCallback.java new file mode 100644 index 0000000..04d3288 --- /dev/null +++ b/docker-connector/src/com/axonivy/connector/docker/AbstractResultCallback.java @@ -0,0 +1,68 @@ +package com.axonivy.connector.docker; + +import java.io.Closeable; +import java.io.IOException; + +import com.github.dockerjava.api.async.ResultCallback; + +abstract class AbstractResultCallback implements ResultCallback { + + enum State { + CREATED, + RUNNING, + ERROR, + COMPLETE, + + } + private AbstractResultCallback.State state = State.CREATED; + private Closeable closeable; + protected StringBuilder builder = new StringBuilder(); + private Throwable error = null; + + @Override + public synchronized void close() { + try { + this.closeable.close(); + } catch (IOException ex) { + error = ex; + } + } + + @Override + public synchronized void onStart(Closeable c) { + this.closeable = c; + this.state = State.RUNNING; + } + + @Override + public synchronized void onError(Throwable e) { + this.state = State.ERROR; + this.error = e; + close(); + notifyAll(); + } + + @Override + public synchronized void onComplete() { + this.state = State.COMPLETE; + close(); + notifyAll(); + } + + public synchronized String await() { + while (state == State.RUNNING || state == State.CREATED) { + try { + wait(); + } catch (InterruptedException ex) { + throw new RuntimeException(ex); + } + } + if (error != null) { + if (error instanceof RuntimeException re) { + throw re; + } + throw new RuntimeException(error); + } + return builder.toString(); + } +} \ No newline at end of file diff --git a/docker-connector/src/com/axonivy/connector/docker/ExecuteResultCallback.java b/docker-connector/src/com/axonivy/connector/docker/ExecuteResultCallback.java new file mode 100644 index 0000000..8937cad --- /dev/null +++ b/docker-connector/src/com/axonivy/connector/docker/ExecuteResultCallback.java @@ -0,0 +1,13 @@ +package com.axonivy.connector.docker; + +import java.nio.charset.StandardCharsets; + +import com.github.dockerjava.api.model.Frame; + +class ExecuteResultCallback extends AbstractResultCallback { + + @Override + public synchronized void onNext(Frame frame) { + builder.append(new String(frame.getPayload(), StandardCharsets.UTF_8)); + } +} \ No newline at end of file diff --git a/docker-connector/src/com/axonivy/connector/docker/IvyDockerClient.java b/docker-connector/src/com/axonivy/connector/docker/IvyDockerClient.java new file mode 100644 index 0000000..0ab815b --- /dev/null +++ b/docker-connector/src/com/axonivy/connector/docker/IvyDockerClient.java @@ -0,0 +1,137 @@ +package com.axonivy.connector.docker; + +import java.nio.file.Path; +import java.time.Duration; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.apache.hc.core5.http.NoHttpResponseException; + +import com.github.dockerjava.api.DockerClient; +import com.github.dockerjava.api.command.CreateContainerCmd; +import com.github.dockerjava.api.command.ListContainersCmd; +import com.github.dockerjava.api.model.Network; +import com.github.dockerjava.core.DefaultDockerClientConfig; +import com.github.dockerjava.core.DockerClientImpl; +import com.github.dockerjava.httpclient5.ApacheDockerHttpClient; + +import ch.ivyteam.ivy.environment.Ivy; + +public class IvyDockerClient { + + private static final IvyDockerClient INSTANCE = new IvyDockerClient(); + private DockerClient client; + + private IvyDockerClient() { + try { + client = createDockerClient(); + } catch (Exception ex) { + Ivy.log().error("Could not create docker client", ex); + } + } + + public static IvyDockerClient instance() { + return INSTANCE; + } + + private static DockerClient createDockerClient() { + var dockerUrl = Ivy.var().get("Docker.URL"); + var config = DefaultDockerClientConfig.createDefaultConfigBuilder() + .withDockerHost(dockerUrl) + .build(); + + var httpClient = new ApacheDockerHttpClient.Builder() + .dockerHost(config.getDockerHost()) + .maxConnections(100) + .connectionTimeout(Duration.ofSeconds(30)) + .responseTimeout(Duration.ofSeconds(45)) + .build(); + + var docker = DockerClientImpl.getInstance(config, httpClient); + return docker; + } + + public CreateContainerCmd createContainerCmd(String image) { + var resp = client.listImagesCmd().withFilter("reference", List.of(image)).exec(); + if (resp.isEmpty()) { + var result = new PullResultCallback(); + client.pullImageCmd(image).exec(result); + result.await(); + } + return client.createContainerCmd(image); + } + + public ListContainersCmd listContainersCmd() { + return client.listContainersCmd(); + } + + public void startContainer(String id) { + retry(() -> client.startContainerCmd(id).exec()); + Ivy.log().info("Container "+id+" started"); + } + + public void stopContainer(String id) { + retry(() -> client.stopContainerCmd(id).exec()); + Ivy.log().info("Container "+id+" stopped"); + } + + public void removeContainer(String id) { + retry(() -> client.removeContainerCmd(id).exec()); + Ivy.log().info("Container "+id+" removed"); + } + + public void executeInContainer(String id, String... command) { + var cmd = client.execCreateCmd(id) + .withCmd(command) + .withAttachStderr(true) + .withAttachStdout(true) + .withTty(true) + .exec(); + var res = new ExecuteResultCallback(); + client.execStartCmd(cmd.getId()) + .withDetach(false) + .withTty(true) + .exec(res); + var cmdStr = Arrays.stream(command).collect(Collectors.joining(" ")); + Ivy.log().info("Execute '"+cmdStr+"' in container "+id+":\n" + res.await()); + } + + public String createNetwork(String name) { + return client.createNetworkCmd().withName(name).exec().getId(); + } + + public Optional findNetwork(String name) { + return client.listNetworksCmd().withFilter("name", List.of(name)).exec().stream().findAny(); + } + + public void connectContainerToNetwork(String id, String networkId) { + client.connectToNetworkCmd().withContainerId(id).withNetworkId(networkId).exec(); + } + + public void copyToContainer(Path hostPath, String containerId, String containerPath) { + client.copyArchiveToContainerCmd(containerId) + .withHostResource(hostPath.toString()) + .withRemotePath(containerPath) + .exec(); + } + + private void retry(Runnable r) { + int retry = 0; + while (true) { + try { + r.run(); + return; + } catch (RuntimeException ex) { + if (! (ex.getCause() instanceof NoHttpResponseException)) { + throw ex; + } + retry++; + if (retry >= 3) { + throw ex; + } + } + } + } +} diff --git a/docker-connector/src/com/axonivy/connector/docker/PullResultCallback.java b/docker-connector/src/com/axonivy/connector/docker/PullResultCallback.java new file mode 100644 index 0000000..2e9d1e1 --- /dev/null +++ b/docker-connector/src/com/axonivy/connector/docker/PullResultCallback.java @@ -0,0 +1,12 @@ +package com.axonivy.connector.docker; + +import com.github.dockerjava.api.model.PullResponseItem; + +class PullResultCallback extends AbstractResultCallback{ + + @Override + public void onNext(PullResponseItem pullItem) { + builder.append(pullItem.getStatus()); + } + +} diff --git a/docker-connector/webContent/icons/docker.png b/docker-connector/webContent/icons/docker.png new file mode 100644 index 0000000..a6c9364 Binary files /dev/null and b/docker-connector/webContent/icons/docker.png differ diff --git a/pom.xml b/pom.xml index 517336b..468789a 100644 --- a/pom.xml +++ b/pom.xml @@ -1,8 +1,8 @@ 4.0.0 com.axonivy.market - my-product - my-product-modules + docker-connector + docker-connector-modules 10.0.0-SNAPSHOT pom