diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 6c834410..1409eb80 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -22,7 +22,7 @@ The `publish-cws-image` job is the CD component of the workflow, triggered upon - [**Services**](https://docs.github.com/en/actions/using-containerized-services/about-service-containers): - MariaDB - - Image: mariadb:10.3 + - Image: mariadb:10.6 - Ports: 3306:3306 - [**checkout**](https://github.com/marketplace/actions/checkout): This action checks out the repository under `$GITHUB_WORKSPACE`, so the workflow can access it. - Set up JDK 11: diff --git a/.github/workflows/camunda.yml b/.github/workflows/camunda.yml index 410172b5..6b6072fd 100644 --- a/.github/workflows/camunda.yml +++ b/.github/workflows/camunda.yml @@ -21,7 +21,7 @@ jobs: services: mdb103: - image: mariadb:10.3 + image: mariadb:10.6 ports: - 3306:3306 env: @@ -46,6 +46,13 @@ jobs: chmod +x generate-certs.sh ./generate-certs.sh + - name: Set up Keystore storepass + run: | + mkdir ~/.cws/ + chmod 700 ~/.cws/ + echo ${{ secrets.KEYSTORE_PASSWORD }} > ~/.cws/creds + chmod 600 ~/.cws/creds + - name: Download Logstash uses: carlosperate/download-file-action@v1 with: @@ -144,7 +151,7 @@ jobs: services: mdb103: - image: mariadb:10.3 + image: mariadb:10.6 ports: - 3306:3306 env: @@ -169,6 +176,13 @@ jobs: chmod +x generate-certs.sh ./generate-certs.sh + - name: Set up Keystore storepass + run: | + mkdir ~/.cws/ + chmod 700 ~/.cws/ + echo ${{ secrets.KEYSTORE_PASSWORD }} > ~/.cws/creds + chmod 600 ~/.cws/creds + - name: Download Logstash uses: carlosperate/download-file-action@v1 with: diff --git a/.github/workflows/ldap.yml b/.github/workflows/ldap.yml index 03a887d2..22fbfd3f 100644 --- a/.github/workflows/ldap.yml +++ b/.github/workflows/ldap.yml @@ -21,7 +21,7 @@ jobs: services: mdb103: - image: mariadb:10.3 + image: mariadb:10.6 ports: - 3306:3306 env: @@ -46,6 +46,13 @@ jobs: chmod +x generate-certs.sh ./generate-certs.sh + - name: Set up Keystore storepass + run: | + mkdir ~/.cws/ + chmod 700 ~/.cws/ + echo ${{ secrets.KEYSTORE_PASSWORD }} > ~/.cws/creds + chmod 600 ~/.cws/creds + - name: Download Logstash uses: carlosperate/download-file-action@v1 with: diff --git a/.gitignore b/.gitignore index d3b907a3..e866a95a 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,4 @@ install/logging/logstash-*.zip /jacoco-reports /test-screenshots -*.cnf \ No newline at end of file +*.cnf diff --git a/README.md b/README.md index c7f53b0b..8196bc6f 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ See the [wiki](https://github.com/NASA-AMMOS/common-workflow-service/wiki) for m - For Home-brew users: - Install Maven using: `brew install maven` - Verify installation using: `mvn -v` -- [**Docker**](https://docs.docker.com/get-docker/): Used to run external Elasticsearch, and create and configure mariaDB database container +- [**Docker**](https://docs.docker.com/get-docker/): Used to run external Elasticsearch, and create and configure MariaDB database container - Recommended minimum system requirements from Docker Resources window: - CPUs: 5 - Memory: 14.00 GB @@ -34,7 +34,7 @@ See the [wiki](https://github.com/NASA-AMMOS/common-workflow-service/wiki) for m - **Logstash 8.8.0+**: Download Logstash for your platform. Uncompress it (only if it is a .tar.gz) and then ZIP back it up with the filename 'logstash-8.8.0.zip' and place in `install/logging/`. This is a temporary workaround while we clean up our installation process. You can find the zip download [here](https://www.elastic.co/downloads/logstash). - **Elasticsearch 8.8.0+**: CWS requires an externally-configured elasticsearch cluster to be set up. You can use an SSL Secure Elasticsearch with or without authentication, or an Insecure HTTP Elasticsearch. - The "Elasticsearch Setup" instruction below provides a contained Dockerized way of running Elasticsearch. This serves as an alternative to installing Elasticsearch. -- Tomcat **keystore and truststore files** (needed for CWS web console to work properly): +- Tomcat **keystore, truststore, storepass files** (needed for CWS web console to work properly). To generate an open-source **.keystore** and **cws_truststore.jks** use the script `./generate-certs.sh` [here](https://github.com/NASA-AMMOS/common-workflow-service/tree/develop/cws-certs) - You will need to add your own Tomcat keystore file to this path: `install/.keystore` - You will need to add your own truststore file to this path: `install/tomcat_lib/cws_truststore.jks` - See: https://tomcat.apache.org/tomcat-9.0-doc/ssl-howto.html @@ -44,15 +44,19 @@ See the [wiki](https://github.com/NASA-AMMOS/common-workflow-service/wiki) for m - Check the exact version installed using `/usr/libexec/java_home -V` - Add to your Shell startup (e.g. .zprofile): `export JAVA_HOME=$(/usr/libexec/java_home -v X.X.X)` - Replace the X.X.X version above with the OpenJDK 17 output from the `/usr/libexec/java_home -V` command. + - **Store Your Keystore Password**: You will need to add your own creds file, which carries the keystore password, to this path: `~/.cws/creds` + - Set the permissions for the **~/.cws/** directory and **creds** file as Owner-Only. + - **~/.cws/** directory: `chmod 700 ~/.cws/` + - **~/.cws/creds** file: `chmod 600 ~/.cws/creds` ### **Development Environment Configuration** ### _MariaDB Setup_ -Generate mariaDB Docker Container and Create Database Instance for CWS: +Generate MariaDB Docker Container and Create Database Instance for CWS: ``` -docker run -d -p 3306:3306 -e MYSQL_DATABASE=__DB_NAME__ -e MYSQL_ROOT_PASSWORD=__ROOT_PW__ -e TZ=America/Los_Angeles --name mdb103 mariadb:10.3 +docker run -d -p 3306:3306 -e MYSQL_DATABASE=__DB_NAME__ -e MYSQL_ROOT_PASSWORD=__ROOT_PW__ -e TZ=America/Los_Angeles --name mdb106 mariadb:10.6 ``` Replace `__DB_NAME__` with your desired database name. @@ -60,17 +64,17 @@ Replace `__ROOT_PW__` with your desired password. `__DB_NAME__` and `__ROOT_PW__` must match parameters set in script file: `.sh` -Directly access mariaDB with: +Directly access MariaDB with: ``` mysql -h 127.0.0.1 -u root -p ``` Enter the password above when prompted. -_CWS must have been built, in this case using a build script, in order to directly access mariaDB with the MySQL monitor, as the build +_CWS must have been built, in this case using a build script, in order to directly access MariaDB with the MySQL monitor, as the build script contains required information to access the database. See the **Building CWS** section for an example build script._ -_Make sure `cws_dev` database in created mariaDB instance before moving forward to build CWS_ +_Make sure `cws_dev` database in created MariaDB instance before moving forward to build CWS_ ### _Elasticsearch Setup_ Open new Shell terminal designated for running ElasticSearch. @@ -180,6 +184,8 @@ Start `test.sh` script by running: This will produce jacoco reports with code coverage measurements. +## [Adaptation Setup Guide](cws-adaptation/README.md) + # Contributing Please see our [contribution guidelines](https://github.com/NASA-AMMOS/common-workflow-service/blob/main/CONTRIBUTING.md). diff --git a/ci/ci.sh b/ci/ci.sh index 387bc048..de585416 100755 --- a/ci/ci.sh +++ b/ci/ci.sh @@ -62,6 +62,7 @@ function worker_conf_data() { fi } +check_java_requirements cat > ci_console.conf.template <<- EOF cam_server_url=NA @@ -122,6 +123,9 @@ default_cws_auth_scheme=CAMUNDA default_history_level=full default_shutdown_port=38005 metrics_publishing_interval=10 +camunda_version=${CAMUNDA_VER} +java_version=${JAVA_HOME_VERSION} +java_home=${JAVA_HOME} EOF @@ -180,6 +184,9 @@ aws_cloudwatch_endpoint=monitoring.us-west-1.amazonaws.com default_history_level=full default_shutdown_port=38005 metrics_publishing_interval=10 +camunda_version=${CAMUNDA_VER} +java_version=${JAVA_HOME_VERSION} +java_home=${JAVA_HOME} EOF diff --git a/create_server_dist.sh b/create_server_dist.sh index 7312733c..6c5f2f89 100755 --- a/create_server_dist.sh +++ b/create_server_dist.sh @@ -69,6 +69,7 @@ cp ${INSTALL_DIR}/tomcat_lib/css-jaas.cfg ${CONFIG_TEMPLATES cp ${INSTALL_DIR}/tomcat_bin/setenv.sh ${CONFIG_TEMPLATES_DIR}/tomcat_bin cp ${INSTALL_DIR}/tomcat_conf/bpm-platform.xml ${CONFIG_TEMPLATES_DIR}/tomcat_conf cp ${INSTALL_DIR}/tomcat_conf/server.xml ${CONFIG_TEMPLATES_DIR}/tomcat_conf +cp ${INSTALL_DIR}/tomcat_conf/server_adaptation.xml ${CONFIG_TEMPLATES_DIR}/tomcat_conf cp ${INSTALL_DIR}/tomcat_conf/web.xml ${CONFIG_TEMPLATES_DIR}/tomcat_conf cp ${INSTALL_DIR}/tomcat_conf/ldap_plugin_bean.xml ${CONFIG_TEMPLATES_DIR}/tomcat_conf cp ${INSTALL_DIR}/tomcat_conf/ldap_plugin_ref.xml ${CONFIG_TEMPLATES_DIR}/tomcat_conf @@ -186,6 +187,17 @@ awk 'NR==FNR { a[n++]=$0; next } cp ${INSTALL_DIR}/sql/core.afterstartup.sql.template ${CWS}/sql/cws/core.afterstartup.sql +if [[ -f ${INSTALL_DIR}/sql/adaptation.sql.template && -f ${INSTALL_DIR}/sql/adaptation_core.sql.template && -f ${INSTALL_DIR}/sql/adaptation_external.sql.template ]]; then + print "Building adaptation (external) sql..." + awk 'NR==FNR { a[n++]=$0; next } + /__CUSTOM_METHODS_JAVA__/ { for (i=0;i ${CWS}/sql/cws/adaptation.sql + awk 'NR==FNR { a[n++]=$0; next } + /__CUSTOM_METHODS_JAVA__/ { for (i=0;i ${CWS}/sql/cws/adaptation_core.sql + awk 'NR==FNR { a[n++]=$0; next } + /__CUSTOM_METHODS_JAVA__/ { for (i=0;i ${CWS}/sql/cws/adaptation_external.sql +fi + + rm ${DIST}/snippets.java rm ${DIST}/snippets.java.bak diff --git a/cws-adaptation/README.md b/cws-adaptation/README.md new file mode 100644 index 00000000..3ee90353 --- /dev/null +++ b/cws-adaptation/README.md @@ -0,0 +1,54 @@ +## Adaptation Setup Guide + +CWS can be adapted and tailored for a mission. This can be done by modifying certain resources and source code of CWS-CORE. + +Create new functionalities by adding: + +* External Database Config +* Custom Java code +* Custom Rest Service API +* Custom Initiators +* etc... + +### Adaptation Database + +Adaptation Database feature lets you connect to a external database separate from that of the main `cws_dev` database. + +**(1)** You must first include the following SQL Template files to the `install/sql/` directory: +* `install/sql/adaptation.sql.template` **(Core Database: `cws_dev`)** +* `install/sql/adaptation_core.sql.template` **(Core Database: `cws_dev`)** +* `install/sql/adaptation_external.sql.template` **(Adaptation Database: `cws_external_db`)** + +**(2)** Create your schema/tables within the added Adaptation SQL Template files. +* Example (`adaptation_external.sql.template`): +``` +CREATE TABLE IF NOT EXISTS `cws_external_table` ( + ... + ... +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; +``` + +**(3)** Write Custom Java Code. + +By referencing your adaptation tables, you can connect and communicate with your external database. + +Write Java custom code that extends from DbService and use the `jdbcTemplate` or `jdbcAdaptationTemplate` JDBC source to query the core and external databases. +``` +jdbcAdaptationTemplate (adaptation external database) +jdbcTemplate (core database) +``` + +### Adaptation Workers Modal + +Custom your Deployment page Workers view with add-ons and filters. + +The UI for the Worker listview is customizable with through the javascript `addAdaptationWorkersInfo` function. + +File: `cws-ui/src/main/webapp/js/adaptation-workers-modal.js` + +Write your custom code here: +``` +function addAdaptationWorkersInfo(dataProcKey, listWorkers) { + return; +} +``` \ No newline at end of file diff --git a/cws-core/src/main/java/jpl/cws/core/db/DbService.java b/cws-core/src/main/java/jpl/cws/core/db/DbService.java index 5366bd04..59842a0a 100644 --- a/cws-core/src/main/java/jpl/cws/core/db/DbService.java +++ b/cws-core/src/main/java/jpl/cws/core/db/DbService.java @@ -9,6 +9,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; @@ -22,9 +23,15 @@ public class DbService { private static final Logger log = LoggerFactory.getLogger(DbService.class); - @Autowired protected JdbcTemplate jdbcTemplate; - @Autowired protected NamedParameterJdbcTemplate namedJdbcTemplate; - + @Autowired + protected JdbcTemplate jdbcTemplate; + + @Autowired + protected NamedParameterJdbcTemplate namedJdbcTemplate; + + @Autowired + protected JdbcTemplate jdbcAdaptationTemplate; + protected static final long SLOW_WARN_THRESHOLD = 100; protected static final int IN_CLAUSE_MAX_ELEMENTS = 100; diff --git a/cws-installer/src/main/java/jpl/cws/task/CwsInstaller.java b/cws-installer/src/main/java/jpl/cws/task/CwsInstaller.java old mode 100644 new mode 100755 index f9148eb9..39725e13 --- a/cws-installer/src/main/java/jpl/cws/task/CwsInstaller.java +++ b/cws-installer/src/main/java/jpl/cws/task/CwsInstaller.java @@ -42,6 +42,9 @@ import org.w3c.dom.*; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilder; +import java.io.FileInputStream; +import java.util.Enumeration; +import java.io.IOException; import java.io.BufferedReader; import java.io.File; @@ -49,6 +52,9 @@ import java.io.IOException; import java.io.InputStreamReader; import java.lang.Math; +import java.util.Date; +import java.text.SimpleDateFormat; +import java.util.*; import java.nio.file.Path; import java.nio.file.Paths; import java.sql.Connection; @@ -65,8 +71,14 @@ import java.util.TimeZone; import javax.naming.AuthenticationNotSupportedException; import javax.naming.AuthenticationException; -import javax.naming.NamingEnumeration; import javax.naming.NamingException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableEntryException; import javax.tools.ToolProvider; @@ -155,6 +167,16 @@ public class CwsInstaller { private static String cws_db_username; private static String cws_db_password; + private static String cws_adapt_use_shared_db; + private static String cws_adapt_db_type; + private static String cws_adapt_db_host; + private static String cws_adapt_db_port; + private static String cws_adapt_db_name; + private static String cws_adapt_db_url; + private static String cws_adapt_db_driver; + private static String cws_adapt_db_username; + private static String cws_adapt_db_password; + private static String cws_auth_scheme; private static String cws_user; private static String cws_user_firstname; @@ -167,6 +189,8 @@ public class CwsInstaller { private static String cws_shutdown_port; private static String cws_tomcat_ajp_port; + private static String cws_keystore_storepass; + private static String cws_smtp_hostname; private static String cws_smtp_port; @@ -212,6 +236,11 @@ public class CwsInstaller { private static String aws_sqs_dispatcher_sqsUrl; private static String aws_sqs_dispatcher_msgFetchLimit; + private static String camunda_version; + + private static String java_version; + private static String java_home = System.getenv("JAVA_HOME"); + private static Boolean reconfigure = false; @@ -253,6 +282,7 @@ public static void main(String args[]) { setupNotificationEmails(); setupTokenExpirationHours(); setupPorts(); + getKeystorePassword(); setupTaskAssigmentEmails(); setupSMTP(); setupElasticsearch(); @@ -344,6 +374,9 @@ private static void init() { ldap_identity_plugin_class = getPreset(LDAP_IDENTITY_PLUGIN_CLASS); ldap_security_filter_class = getPreset(LDAP_SECURITY_FILTER_CLASS); camunda_security_filter_class = getPreset(CAMUNDA_SECURITY_FILTER_CLASS); + camunda_version = getPreset("camunda_version"); + + java_version = getPreset("java_version"); } private static void exit(int status) { @@ -1048,6 +1081,41 @@ private static void setupLimitToRemoveAbandonedWorkersByDays() { } + private static void getKeystorePassword() { + cws_keystore_storepass = getPreset("cws_keystore_storepass"); + + if (cws_keystore_storepass == null) { + Path filePath; + filePath = Paths.get("~/.cws/creds"); + String storepassFilePath = filePath.toString(); + storepassFilePath = storepassFilePath.replaceFirst("^~", System.getProperty("user.home")); + File storepassReadFile = new File(storepassFilePath); + boolean fileExists = storepassReadFile.exists(); + + if (fileExists == true) { + if (!storepassReadFile.canRead()) { + print("ERROR: creds in path '" + "~/.cws/creds" + "' is NOT readable by system user."); + print(" "); + print("WARNING: Read and fulfill the Keystore/Truststore prerequisites before continuing installation: "); + print(" https://github.com/NASA-AMMOS/common-workflow-service?tab=readme-ov-file#prerequisites"); + exit(1); + } + } else { + print("ERROR: creds does NOT exist in path '" + "~/.cws/creds" + "' "); + print(" "); + print("WARNING: Make sure to place creds in the correct path and satisfy the following Keystore/Truststore prerequisites: "); + print(" https://github.com/NASA-AMMOS/common-workflow-service?tab=readme-ov-file#prerequisites"); + exit(1); + } + + try { + cws_keystore_storepass = Files.readString(Paths.get(storepassFilePath)).trim(); + } catch (IOException e) { + log.error("Read-in Keystore Storepass ERROR: " + e.getMessage()); + } + } + } + private static void setupPorts() { // PROMPT USER FOR CWS WEB PORT cws_tomcat_connector_port = getPreset("cws_web_port"); @@ -1659,6 +1727,34 @@ private static void showInstallationInfo() { print("Database User = " + cws_db_username); print("Database Password = ****** (hidden) "); print("...................................................................................."); + + cws_adapt_use_shared_db = getPreset("adaptation_use_shared_db"); + cws_adapt_db_type = getPreset("adaptation_db_type"); + cws_adapt_db_host = getPreset("adaptation_db_host"); + cws_adapt_db_port = getPreset("adaptation_db_port"); + cws_adapt_db_name = getPreset("adaptation_db_name"); + cws_adapt_db_username = getPreset("adaptation_db_username"); + cws_adapt_db_password = getPreset("adaptation_db_password"); + cws_adapt_db_url = "jdbc:" + cws_adapt_db_type + "://" + cws_adapt_db_host + ":" + cws_adapt_db_port + "/" + cws_adapt_db_name + "?autoReconnect=true"; + + if (cws_adapt_use_shared_db != null) { + if (cws_adapt_use_shared_db.equalsIgnoreCase("y")) { + + if (cws_adapt_db_type.equals("mariadb")) { + cws_adapt_db_driver = "org.mariadb.jdbc.Driver"; + } else if (cws_adapt_db_type.equals("mysql")) { + cws_adapt_db_driver = "com.mysql.jdbc.Driver"; + } + print(" CWS Adapt Database "); + print(" Database Type = " + cws_adapt_db_type); + print(" Database URL = " + cws_adapt_db_url); + print(" Database Driver = " + cws_adapt_db_driver); + print(" Database User = " + cws_adapt_db_username); + print(" Database Password = ****** (hidden) "); + print("...................................................................................."); + } + } + if (cws_auth_scheme.equals("LDAP")) { print("LDAP User = " + cws_user); } @@ -1670,6 +1766,7 @@ private static void showInstallationInfo() { print("Admin Last Name = " + cws_user_lastname); print("Admin Email = " + cws_user_email); } + print("...................................................................................."); print("CWS web port = " + cws_tomcat_connector_port); print("CWS SSL port = " + cws_tomcat_ssl_port); print("CWS AJP port = " + cws_tomcat_ajp_port); @@ -1766,6 +1863,9 @@ private static void validateConfig() { // Check that user provided Elasticsearch service is up and healthy warningCount += validateElasticsearch(); + // Check that keystore and truststore is valid, not expired + warningCount += validateKeystoreTruststore(); + if (installWorker && !installConsole) { // Validate the AMQ host/port for worker only installations. warningCount += validateAmqConfig(); @@ -2371,6 +2471,55 @@ private static int validateElasticsearch() { } } + /** + * Validates the .keystore file in tomcat_lab. Checks for correct file name and expiration + */ + private static int validateKeystoreTruststore() { + print("checking that user provided valid .keystore file and certificate chain..."); + Path filePath; + filePath = Paths.get(cws_tomcat_conf + SEP + ".keystore"); + String keystoreFilePath = filePath.toString(); + long ONE_DAY_MS = 24 * 60 * 60 * 1000; // 24 hours or 1 day + try { + KeyStore ks = KeyStore.getInstance("JKS"); + ks.load(new FileInputStream(keystoreFilePath), cws_keystore_storepass.toCharArray()); + Enumeration aliases = ks.aliases(); + while(aliases.hasMoreElements()) { + String keystoreRoot = (String) aliases.nextElement(); + Date expirationDate = ((X509Certificate) ks.getCertificate(keystoreRoot)).getNotAfter(); + Date currentTime = new Date(); + long daysInterval = expirationDate.getTime() - currentTime.getTime(); + long numDays = daysInterval / (ONE_DAY_MS); + if (numDays <= 0) { + print(" [WARNING]"); + print(" The Certificate Chain in Keystore '" + keystoreFilePath + "' is expired. "); + print(" Expiration Date: " + expirationDate); + print(""); + return 1; + } else if (numDays > 0 && numDays < 90) { + print(" [OK]"); + print(" NOTICE: Make sure to renew the certificates within the .keystore certificate chain soon."); + print(" Certificate(s): '" + keystoreFilePath + "' "); + print(" Expiration Date: " + expirationDate); + print(" Days Until expiration: " + numDays + " days"); + print(""); + return 0; + } else { + print(" [OK]"); + print(""); + } + } + } catch (Exception e) { + print(" [WARNING]"); + print(" The path '" + cws_tomcat_conf + SEP + "' "); + print(" may NOT contain .keystore file OR holds a keystore that is mismatched with password in '~/.cws/creds' or cws_keystore_storepass configuration."); + print(""); + log.error("Keystore Storepass ERROR: " + e.getMessage()); + return 1; + } + return 0; // OK + } + /** * Validates that some sort of time syncing service * such as NTP or chrony is running on this installation machine. @@ -2478,6 +2627,8 @@ private static void createFreshWorkDir() { Paths.get(config_work_dir + SEP + "tomcat_conf" + SEP + "bpm-platform.xml")); copy(Paths.get( config_templates_dir + SEP + "tomcat_conf" + SEP + "server.xml"), Paths.get(config_work_dir + SEP + "tomcat_conf" + SEP + "server.xml")); + copy(Paths.get( config_templates_dir + SEP + "tomcat_conf" + SEP + "server_adaptation.xml"), + Paths.get(config_work_dir + SEP + "tomcat_conf" + SEP + "server_adaptation.xml")); copy(Paths.get( config_templates_dir + SEP + "tomcat_conf" + SEP + "web.xml"), Paths.get(config_work_dir + SEP + "tomcat_conf" + SEP + "web.xml")); copy(Paths.get( config_templates_dir + SEP + "engine-rest_mods" + SEP + "web.xml"), @@ -2546,6 +2697,29 @@ private static void updateFiles() throws IOException { content = content.replace("__CWS_DB_DRIVER__", cws_db_driver); content = content.replace("__CWS_DB_USERNAME__", cws_db_username); content = content.replace("__CWS_DB_PASSWORD__", cws_db_password); + + writeToFile(filePath, content); + copy( + Paths.get(config_work_dir + SEP + "tomcat_conf" + SEP + "server_adaptation.xml"), + Paths.get(cws_tomcat_root + SEP + "conf" + SEP + "server_adaptation.xml")); + if (cws_adapt_db_url != null && cws_adapt_db_driver != null && + cws_adapt_db_username != null && cws_adapt_db_password != null) { + + // Fill in the __ADAPTATION_SERVER_RESOURCE__ + String serverAdaptationContent = getFileContents( + Paths.get(config_work_dir + SEP + "tomcat_conf" + SEP + "server_adaptation.xml")); + content = content.replace(""); + content = content.replace("__CWS_ADAPTATION_BEAN__", "\n" + + "\t\t\n" + + "\t"); + } else { + content = content.replace("__CWS_ADAPTATION_JNDI__", ""); + content = content.replace("__CWS_ADAPTATION_BEAN__", ""); + } + content = content.replace("__CWS_DB_DRIVER__", cws_db_driver); content = content.replace("__CWS_DB_URL__", cws_db_url); content = content.replace("__CWS_DB_USERNAME__", cws_db_username); @@ -2842,6 +3027,10 @@ private static void updateCwsUiProperties() throws IOException { content = content.replace("__AWS_SQS_DISPATCHER_MSG_FETCH_LIMIT__", aws_sqs_dispatcher_msgFetchLimit); } + content = content.replace("__CWS_CAMUNDA_VERSION__", camunda_version); + content = content.replace("__CWS_JAVA_VERSION__", java_version); + content = content.replace("__CWS_JAVA_HOME__", java_home); + writeToFile(filePath, content); copy( Paths.get(config_work_dir + SEP + "cws-ui" + SEP + "cws-ui.properties"), @@ -2853,6 +3042,18 @@ private static void updateCwsUiConfig() throws IOException { print(" Updating cws-ui/applicationContext.xml..."); Path path = Paths.get(config_work_dir + SEP + "cws-ui" + SEP + "applicationContext.xml"); String content = getFileContents(path); + + if (cws_adapt_db_url != null && cws_adapt_db_driver != null && + cws_adapt_db_username != null && cws_adapt_db_password != null) { + content = content.replace("__CWS_ADAPTATION_JNDI__", ""); + content = content.replace("__CWS_ADAPTATION_BEAN__", "\n" + + "\t\t\n" + + "\t"); + } else { + content = content.replace("__CWS_ADAPTATION_JNDI__", ""); + content = content.replace("__CWS_ADAPTATION_BEAN__", ""); + } + content = content.replace("__CWS_DB_DRIVER__", cws_db_driver); content = content.replace("__CWS_DB_URL__", cws_db_url); content = content.replace("__CWS_DB_USERNAME__", cws_db_username); @@ -3249,4 +3450,4 @@ private static void setPreset(String key, String value) { } } -} \ No newline at end of file +} diff --git a/cws-service/src/main/java/jpl/cws/controller/MvcCore.java b/cws-service/src/main/java/jpl/cws/controller/MvcCore.java old mode 100644 new mode 100755 index 72cd360a..0c246098 --- a/cws-service/src/main/java/jpl/cws/controller/MvcCore.java +++ b/cws-service/src/main/java/jpl/cws/controller/MvcCore.java @@ -40,6 +40,11 @@ public class MvcCore { @Value("${cws.history.days.to.live}") private String historyDaysToLive; @Value("${cws.history.level}") private String historyLevel; + @Value("${cws.camunda.version}") private String camundaVersion; + + @Value("${cws.java.home}") private String javaHome; + @Value("${cws.java.version}") private String javaVersion; + public MvcCore() {} protected ModelAndView buildModel(String page, String message) { @@ -183,7 +188,12 @@ protected ModelAndView buildConfigurationModel(String message) { model.addObject("tomcatWebapps", tomcatWebapps); model.addObject("historyDaysToLive", historyDaysToLive); model.addObject("historyLevel", historyLevel); - + + model.addObject("camundaVersion", camundaVersion); + + model.addObject("javaHome", javaHome); + model.addObject("javaVersion", javaVersion); + DiskUsage diskUsage = cwsConsoleService.getDiskUsage(); model.addObject("databaseSize", diskUsage.databaseSize); diff --git a/cws-ui/src/main/webapp/js/adaptation-workers-modal.js b/cws-ui/src/main/webapp/js/adaptation-workers-modal.js new file mode 100644 index 00000000..a8870084 --- /dev/null +++ b/cws-ui/src/main/webapp/js/adaptation-workers-modal.js @@ -0,0 +1,8 @@ +// override with js code file in your adaptation project for example like this +// cp your-cws-adaptation/src/main/resources/cws-ui/adaptation-deployments.js common-workflow-service/cws-ui/src/web/main/webapp/js/adaptation-deployments.js +// This adaptation allows extra information to be added to each worker. The particular use case that +// drove this need is a request to add the aws scaling class each worker belongs to +function addAdaptationWorkersInfo(dataProcKey, listWorkers) { + return; // Common workflow behavior is to do nothing +} + diff --git a/cws-ui/src/main/webapp/js/adaptation-workers.js b/cws-ui/src/main/webapp/js/adaptation-workers.js index 48f770bc..10949ea1 100644 --- a/cws-ui/src/main/webapp/js/adaptation-workers.js +++ b/cws-ui/src/main/webapp/js/adaptation-workers.js @@ -3,4 +3,3 @@ function adaptationWorkersReady() { return; // CWS core behavior is to do nothing here } - diff --git a/install/configure.sh b/install/configure.sh index 2dbf3db2..fd853d23 100755 --- a/install/configure.sh +++ b/install/configure.sh @@ -318,16 +318,65 @@ if [[ "${CWS_INSTALL_TYPE}" = "1" ]] || [[ "${CWS_INSTALL_TYPE}" = "2" ]]; then # Record the fact that tables have been created touch ${ROOT}/.databaseTablesCreated + # Create any adaptation tables, if provided - if [[ -f ${ROOT}/sql/cws/adaptation.sql ]]; then - print "Creating adaptation tables..." - mysql --defaults-file=${ROOT}/config/my.cnf ${DB_NAME} < ${ROOT}/sql/cws/adaptation.sql - if [[ $? -gt 0 ]]; then - print "ERROR: Problem creating adaptation tables." - print " Please check your database configuration and/or adaptation script '${ROOT}/sql/cws/adaptation.sql', and try again." - rm -rf ${ROOT}/config/my.cnf - exit 1 - fi + if [[ -f ${ROOT}/sql/cws/adaptation.sql && -f ${ROOT}/sql/cws/adaptation_core.sql && -f ${ROOT}/sql/cws/adaptation_external.sql ]]; then + print "Checking for Adaptation DB Settings..." + ADAPT_USE_SHARED_DB=`grep adaptation_use_shared_db ${CWS_INSTALLER_PRESET_FILE} | grep -v "^#" | cut -d"=" -f 2` + + if [[ "${ADAPT_USE_SHARED_DB}" == "y" ]]; then + ADAPT_DB_HOST=`grep adaptation_db_host ${CWS_INSTALLER_PRESET_FILE} | grep -v "^#" | cut -d"=" -f 2` + ADAPT_DB_NAME=`grep adaptation_db_name ${CWS_INSTALLER_PRESET_FILE} | grep -v "^#" | cut -d"=" -f 2` + ADAPT_DB_USER=`grep adaptation_db_username ${CWS_INSTALLER_PRESET_FILE} | grep -v "^#" | cut -d"=" -f 2` + ADAPT_DB_PASS=`grep adaptation_db_password ${CWS_INSTALLER_PRESET_FILE} | grep -v "^#" | cut -d"=" -f 2` + + echo "[mysql]" > ${ROOT}/config/myadapt.cnf + echo "host=${ADAPT_DB_HOST}" >> ${ROOT}/config/myadapt.cnf + echo "user=\"${ADAPT_DB_USER}\"" >> ${ROOT}/config/myadapt.cnf + echo "password=\"${ADAPT_DB_PASS}\"" >> ${ROOT}/config/myadapt.cnf + chmod 644 ${ROOT}/config/myadapt.cnf + + + # ---------------------------------------- + print "Your adaptation database configuration is:" + print " DB HOST: ${ADAPT_DB_HOST}" + print " DB NAME: ${ADAPT_DB_NAME}" + print " DB USER: ${ADAPT_DB_USER}" + print "This script will now create the database necessary for CWS to function." + + + print "Checking whether database ${ADAPT_DB_NAME} already exists..." + RES=`mysql --defaults-file=${ROOT}/config/myadapt.cnf -e "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '${ADAPT_DB_NAME}'"` + + if [[ $? -gt 0 ]]; then + print "ERROR: Problem checking for database. " + print " Please check your database configuration, and try again." + rm -f ${ROOT}/config/myadapt.cnf + exit 1 + fi + print " Database ${ADAPT_DB_NAME} exists." + + print "Creating adaptation tables in External DB..." + mysql --defaults-file=${ROOT}/config/my.cnf ${DB_NAME} < ${ROOT}/sql/cws/adaptation_core.sql + mysql --defaults-file=${ROOT}/config/myadapt.cnf ${ADAPT_DB_NAME} < ${ROOT}/sql/cws/adaptation_external.sql + if [[ $? -gt 0 ]]; then + print "ERROR: Problem creating adaptation tables." + print " Please check your database configuration and/or adaptation script '${ROOT}/sql/cws/adaptation_external.sql', and try again." + rm -rf ${ROOT}/config/myadapt.cnf + exit 1 + fi + else + print "Creating adaptation tables in Default Core DB..." + if [[ -f ${ROOT}/sql/cws/adaptation.sql ]]; then + mysql --defaults-file=${ROOT}/config/my.cnf ${DB_NAME} < ${ROOT}/sql/cws/adaptation.sql + if [[ $? -gt 0 ]]; then + print "ERROR: Problem creating adaptation tables." + print " Please check your database configuration and/or adaptation script '${ROOT}/sql/cws/adaptation.sql', and try again." + rm -rf ${ROOT}/config/my.cnf + exit 1 + fi + fi + fi # Record the fact that we applied a database adaptation touch ${ROOT}/.adaptationTablesCreated @@ -346,5 +395,6 @@ if [[ "${CWS_INSTALL_TYPE}" = "1" ]] || [[ "${CWS_INSTALL_TYPE}" = "2" ]]; then fi rm -f ${ROOT}/config/my.cnf +rm -f ${ROOT}/config/myadapt.cnf print "Finished" diff --git a/install/context.xml b/install/context.xml index b5adf33b..3ff3c4e7 100644 --- a/install/context.xml +++ b/install/context.xml @@ -36,4 +36,6 @@ + + \ No newline at end of file diff --git a/install/cws-engine/applicationContext.xml b/install/cws-engine/applicationContext.xml index 914c671d..76f73775 100644 --- a/install/cws-engine/applicationContext.xml +++ b/install/cws-engine/applicationContext.xml @@ -22,6 +22,8 @@ + __CWS_ADAPTATION_JNDI__ + @@ -30,6 +32,8 @@ + __CWS_ADAPTATION_BEAN__ + diff --git a/install/cws-ui/adaptation-workers-modal.ftl b/install/cws-ui/adaptation-workers-modal.ftl new file mode 100644 index 00000000..7c9e4e67 --- /dev/null +++ b/install/cws-ui/adaptation-workers-modal.ftl @@ -0,0 +1,9 @@ + + diff --git a/install/cws-ui/applicationContext.xml b/install/cws-ui/applicationContext.xml index 454551ec..9260dda0 100644 --- a/install/cws-ui/applicationContext.xml +++ b/install/cws-ui/applicationContext.xml @@ -25,6 +25,8 @@ + __CWS_ADAPTATION_JNDI__ + @@ -33,6 +35,8 @@ + __CWS_ADAPTATION_BEAN__ + diff --git a/install/cws-ui/configuration.ftl b/install/cws-ui/configuration.ftl old mode 100644 new mode 100755 index 19e1cdb9..75a3191e --- a/install/cws-ui/configuration.ftl +++ b/install/cws-ui/configuration.ftl @@ -197,6 +197,11 @@ CWS Version ${version} + + Camunda Version + ${camundaVersion} + + CWS Database Type ${dbType} @@ -245,6 +250,14 @@ CWS History Days To Live ${historyDaysToLive} + + Java Version + ${javaVersion} + + + Java Home Path + ${javaHome} + diff --git a/install/cws-ui/cws-ui.properties b/install/cws-ui/cws-ui.properties old mode 100644 new mode 100755 index 957224f0..57600b5d --- a/install/cws-ui/cws-ui.properties +++ b/install/cws-ui/cws-ui.properties @@ -60,4 +60,16 @@ cws.metrics.publishing.interval=__CWS_METRICS_PUBLISHING_INTERVAL__ aws.default.region=__AWS_DEFAULT_REGION__ aws.sqs.dispatcher.sqsUrl=__AWS_SQS_DISPATCHER_SQS_URL__ aws.sqs.dispatcher.msgFetchLimit=__AWS_SQS_DISPATCHER_MSG_FETCH_LIMIT__ -aws.sqs.dispatcher.maxThreads=100 \ No newline at end of file +aws.sqs.dispatcher.maxThreads=100 + +# +# CAMUNDA PROPERTIES +# +cws.camunda.version=__CWS_CAMUNDA_VERSION__ + +# +# JAVA PROPERTIES +# +cws.java.version=__CWS_JAVA_VERSION__ +cws.java.home=__CWS_JAVA_HOME__ + diff --git a/install/cws-ui/deployments.ftl b/install/cws-ui/deployments.ftl index fc01e293..cc9b8c32 100644 --- a/install/cws-ui/deployments.ftl +++ b/install/cws-ui/deployments.ftl @@ -9,9 +9,13 @@ + + + + @@ -43,27 +47,35 @@ //GET PROCESS DEFINITIONS AS AN ARRAY (USES FREEMARKER SYNTAX) <#list procDefs as x> - statsVal.${x.key} = {pending:'...', disabled:'...', active:'...', completed:'...', error:'...', fts:'...', incident:'...'}; - var procDef = { - "key": "${x.key}", - "name": "${x.name}", - "version": "${x.version}", - "suspended": "${x.suspended?c}", - "id": "${x.id}" - }; - procDefArray.push(procDef); + statsVal.${x.key} = { + pending: '...', + disabled: '...', + active: '...', + completed: '...', + error: '...', + fts: '...', + incident: '...' + }; + var procDef = { + "key": "${x.key}", + "name": "${x.name}", + "version": "${x.version}", + "suspended": "${x.suspended?c}", + "id": "${x.id}" + }; + procDefArray.push(procDef); #list> // REFRESH THE TEXTUAL STATS SUMMARY function refreshStatUI(name, statsCounts) { var statTotal = - statsCounts.pending + - statsCounts.disabled + - statsCounts.active + - statsCounts.completed + - statsCounts.error + - statsCounts.fts + - statsCounts.incident; + statsCounts.pending + + statsCounts.disabled + + statsCounts.active + + statsCounts.completed + + statsCounts.error + + statsCounts.fts + + statsCounts.incident; var instanceTextString = ""; if (statsCounts.pending) { @@ -93,7 +105,7 @@ $("#stat-txt-" + name).html(instanceTextString); } else { $("#stat-txt-" + name).html( - "No stats for this process" + "No stats for this process" ); } @@ -133,9 +145,9 @@ } /** - * because of the possible additional percentage, calculate the number of - * each dimension corresponding to the adjusted percentage - **/ + * because of the possible additional percentage, calculate the number of + * each dimension corresponding to the adjusted percentage + **/ var statsTemp = {}; statsTemp.pending = statsPercent.pending * statTotal; @@ -147,11 +159,11 @@ statsTemp.incident = statsPercent.incident * statTotal; statTotal = statsTemp.pending + statsTemp.disabled + statsTemp.error + statsTemp.active + - statsTemp.completed + statsTemp.fts + statsTemp.incident; + statsTemp.completed + statsTemp.fts + statsTemp.incident; /** - * recalculate percentage distribution using the recalculated values - **/ + * recalculate percentage distribution using the recalculated values + **/ statsPercent.pending = statsTemp.pending / statTotal * 100; statsPercent.disabled = statsTemp.disabled / statTotal * 100; statsPercent.active = statsTemp.active / statTotal * 100; @@ -201,7 +213,7 @@ return "Process definition was not found. Maybe it was already deleted. Try refreshing the page..."; } else if (message.indexOf("(Running)") > 0) { return "Before deleting this process definition, you must wait for it to finish running or stop it, then disable it on all workers."; - } else { + } else { return "An unknown error occured."; } } @@ -223,8 +235,7 @@ } deleteProcDefEsLogs(proc_def_key); - } - else { + } else { var deleteError = getDeleteErrorMessage(data.message); @@ -296,7 +307,9 @@ // SKIP AN INVALID KEY // THIS IS NECESSARY, IF SOMEHOW AN INVALID PROC GOT SCHEDULED OR PUT IN A DATABASE ROW // - if (statsVal[key] == undefined) { return true; } + if (statsVal[key] == undefined) { + return true; + } // UPDATE THE STATS VALUE ARRAYS // @@ -385,8 +398,8 @@ columns: [ //ICONS COLUMN { - data: { suspended: "suspended", id: "id", key: "key" }, - render: function(data, type) { + data: {suspended: "suspended", id: "id", key: "key"}, + render: function (data, type) { if (type !== 'display') { return data.id; } else { @@ -394,20 +407,20 @@ var returnVal = ``; if (data.suspended == "true") { returnVal += `` - + `` - + ``; + + `` + + ``; } else { returnVal += `` - + ``; + + ``; } - + returnVal += `` - + `` - + `` - + ``; + + `` + + `` + + ``; returnVal += ``; return returnVal; @@ -416,7 +429,7 @@ }, //NAME COLUMN { - data: { name: "name", id: "id", key: "key" }, + data: {name: "name", id: "id", key: "key"}, render: function (data, type) { if (type !== 'display') { return data.name; @@ -435,8 +448,7 @@ } else { if (data === null || data === undefined || data === "null") { return "ERROR"; - } - else { + } else { return data; } } @@ -451,8 +463,7 @@ } else { if (data === null || data === undefined || data === "null") { return "ERROR"; - } - else { + } else { return data; } } @@ -466,29 +477,27 @@ return ""; } else { var html = `view`; + + `data-proc-key="` + data + `">view`; return html; } } }, //STATUS COLUMN { - data: { suspended: "suspended", key: "key" }, + data: {suspended: "suspended", key: "key"}, render: function (data, type) { if (type !== 'display') { if (data.suspended === "true") { return "Suspended"; - } - else { + } else { return "Active"; } } else { var status = ""; var html = ""; if (data.suspended == "true") { - html =`Suspended`; - } - else { + html = `Suspended`; + } else { html = `Active`; } return html; @@ -503,37 +512,37 @@ return ""; } else { var html = `` - + `` - + `` - + `` - + `` - + `` - + `` - + `` - + `` - + `` - + `` - + `` - + `` - + `` - + `` - + `` - + `` - + `` - + `` - + `` - + `` - + `` - + `` - + `No Instance Statistics...` - + ``; + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `No Instance Statistics...` + + ``; return html; } } @@ -543,7 +552,7 @@ rowId: "key", //DISABLES ORDERING ON BUTTON, WORKER, AND INSTANCE STATISTICS COLUMNS (https://datatables.net/reference/option/columnDefs) columnDefs: [ - { orderable: false, targets: [ 0,6,4 ]} + {orderable: false, targets: [0, 6, 4]} ], //SETS DEFAULT ORDERING TO BE THE "NAME" COLUMN, ASCENDING (https://datatables.net/reference/option/order) order: [[1, "asc"]], @@ -551,8 +560,8 @@ "paging": false, //SETS WHAT ELEMENTS ARE CREATED BY DATATABLE AND WHERE ELEMENTS ARE PUT (https://datatables.net/reference/option/dom) dom: "<'above-table-div'<'above-table-buttons'>f>" - + "t" - + "<'below-table-div'i>", + + "t" + + "<'below-table-div'i>", }); //OUR DATA COMES FROM FREEMARKER TEMPLATE - ADD THAT ARRAY TO THE DATATABLE @@ -575,50 +584,48 @@ $("#process-table").DataTable().column(5).search("Active", false, true).draw(); localStorage.setItem(hideSuspendedProcVar, "1"); refreshStats(); - } - else { + } else { $("#process-table").DataTable().column(5).search("").draw(); localStorage.setItem(hideSuspendedProcVar, "0"); refreshStats(); } $("#process-table").DataTable().rows().every(function () { - $("#process-table").DataTable().rows().every( function (rowIdx, tableLoop, rowLoop) { - var status = this.data()["suspended"]; - var procDefKey = this.data()["key"]; - var procDefId = this.data()["id"]; - if (status == "false") { - $("#suspend-" + procDefKey).removeClass("glyphicon-play"); - $("#suspend-" + procDefKey).addClass("glyphicon-pause"); - $("#suspend-" + procDefKey).css("color", "#d9534f"); - $("#btn-suspend-" + procDefKey).attr("onclick", "suspendProcDef('" + procDefId + "', '" + procDefKey + "')"); - $("#status-txt-" + procDefKey).html("Active"); - $("#" + procDefKey).removeClass("disabled"); - $("#pv-" + procDefKey).removeClass("disabled"); - } else { - $("#suspend-" + procDefKey).removeClass("glyphicon-pause"); - $("#suspend-" + procDefKey).addClass("glyphicon-play"); - $("#suspend-" + procDefKey).css("color", "green"); - $("#btn-suspend-" + procDefKey).attr("onclick", "resumeProcDef('" + procDefId + "', '" + procDefKey + "')"); - $("#status-txt-" + procDefKey).html("Suspended"); - $("#" + procDefKey).addClass("disabled"); - $("#pv-" + procDefKey).addClass("disabled"); - } - }); + $("#process-table").DataTable().rows().every(function (rowIdx, tableLoop, rowLoop) { + var status = this.data()["suspended"]; + var procDefKey = this.data()["key"]; + var procDefId = this.data()["id"]; + if (status == "false") { + $("#suspend-" + procDefKey).removeClass("glyphicon-play"); + $("#suspend-" + procDefKey).addClass("glyphicon-pause"); + $("#suspend-" + procDefKey).css("color", "#d9534f"); + $("#btn-suspend-" + procDefKey).attr("onclick", "suspendProcDef('" + procDefId + "', '" + procDefKey + "')"); + $("#status-txt-" + procDefKey).html("Active"); + $("#" + procDefKey).removeClass("disabled"); + $("#pv-" + procDefKey).removeClass("disabled"); + } else { + $("#suspend-" + procDefKey).removeClass("glyphicon-pause"); + $("#suspend-" + procDefKey).addClass("glyphicon-play"); + $("#suspend-" + procDefKey).css("color", "green"); + $("#btn-suspend-" + procDefKey).attr("onclick", "resumeProcDef('" + procDefId + "', '" + procDefKey + "')"); + $("#status-txt-" + procDefKey).html("Suspended"); + $("#" + procDefKey).addClass("disabled"); + $("#pv-" + procDefKey).addClass("disabled"); + } }); + }); }); //INIT STATE OF HIDE SUSPENDED PROC DEF CHECKBOX if (parseInt(localStorage.getItem(hideSuspendedProcVar)) == 0) { $("#hide-sus-btn").prop("checked", false); $("#process-table").DataTable().column(5).search("").draw(); - } - else { + } else { $("#hide-sus-btn").prop("checked", true); $("#process-table").DataTable().column(5).search("Active", false, true).draw(); } //PULL LATEST STATS refreshStats(); - + //INIT STATE OF REFRESH RATE if (parseInt(localStorage.getItem(refreshRateVar)) !== 0) { pageRefId = setInterval(pageRefresh, parseInt(localStorage.getItem(refreshRateVar))); @@ -656,8 +663,7 @@ id = $(this).parent().attr("data-pdk"); if (id) { window.location = "/${base}/processes?procDefKey=" + id + "&status=fail&cache=false"; - } - else { + } else { window.location = "/${base}/processes?status=fail&cache=false"; } }); @@ -665,8 +671,7 @@ id = $(this).parent().attr("data-pdk"); if (id) { window.location = "/${base}/processes?procDefKey=" + id + "&status=complete,resolved&cache=false"; - } - else { + } else { window.location = "/${base}/processes?status=complete,resolved&cache=false"; } }); @@ -674,8 +679,7 @@ id = $(this).parent().attr("data-pdk"); if (id) { window.location = "/${base}/processes?procDefKey=" + id + "&status=pending&cache=false"; - } - else { + } else { window.location = "/${base}/processes?status=pending&cache=false"; } }); @@ -683,8 +687,7 @@ id = $(this).parent().attr("data-pdk"); if (id) { window.location = "/${base}/processes?procDefKey=" + id + "&status=disabled&cache=false"; - } - else { + } else { window.location = "/${base}/processes?status=disabled&cache=false"; } }); @@ -692,8 +695,7 @@ id = $(this).parent().attr("data-pdk"); if (id) { window.location = "/${base}/processes?procDefKey=" + id + "&status=running&cache=false"; - } - else { + } else { window.location = "/${base}/processes?status=running&cache=false"; } }); @@ -701,8 +703,7 @@ id = $(this).parent().attr("data-pdk"); if (id) { window.location = "/${base}/processes?procDefKey=" + id + "&status=failedToStart&cache=false"; - } - else { + } else { window.location = "/${base}/processes?status=failedToStart&cache=false"; } }); @@ -710,8 +711,7 @@ id = $(this).parent().attr("data-pdk"); if (id) { window.location = "/${base}/processes?procDefKey=" + id + "&status=incident&cache=false"; - } - else { + } else { window.location = "/${base}/processes?status=incident&cache=false"; } }); @@ -754,7 +754,7 @@ $("#" + procDefKey).addClass("disabled"); $("#pv-" + procDefKey).addClass("disabled"); }, - error: function(data) { + error: function (data) { console.log("error suspending"); } }) @@ -780,7 +780,7 @@ $("#" + procDefKey).removeClass("disabled"); $("#pv-" + procDefKey).removeClass("disabled"); }, - error: function(data) { + error: function (data) { console.log("error activating"); } }) @@ -789,7 +789,8 @@ - + - - - - - - - - - - 5 second refresh rate - 3 second refresh rate - 1 second refresh rate - Stop auto-refresh - - - - - - Show stats for last Hour - Show stats for last 3 Hours - Show stats for last 6 Hours - Show stats for last 12 Hours - Show stats for last Day - Show stats for last 3 Days - Show stats for last 1 Week - Show stats for last 2 Weeks - Show stats for All Time - - - - - - Process status summary: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - No Summary Statistics... - - - + <#include "sidebar.ftl"> - - - - - Name - Key - Version - Workers - Status - Instance Statistics - - - - - + + ${msg} - + + + Deployed Process Definitions + + + + + + Browse for BPMN file... + + + + + - + - - - - - WARNING! + + + + + 5 second refresh rate + 3 second refresh rate + 1 second refresh rate + Stop auto-refresh + - - - Your browser has been idle for more than 10 minutes. Do you want to resume? + + + + Show stats for last Hour + Show stats for last 3 Hours + Show stats for last 6 Hours + Show stats for last 12 Hours + Show stats for last Day + Show stats for last 3 Days + Show stats for last 1 Week + Show stats for last 2 Weeks + Show stats for All Time + + + + + Process status summary: + - + + + + - - - - - + + + - - - - - Confirm Delete - + + + - - Are you sure you want to delete process definition ''? - - Warning: All data for this process definition will be removed (run history, logs, pending - runs, etc...) - - - Deleting... Please wait. + + - - - - - - - - - - - Delete Failed - - - There was an error deleting process definition ''. - - - Error - + + + - - - - - - - - - - Select one or more workers to enable the process. - + + + - - - - Select All Workers + + - - - - - *It's recommended that this worker always be selected. - This is because all manual tasks (i.e. User Tasks and manual process starts via the - TaskList app) - are initiated via this worker. - - - Note: Grayed out workers are currently down. - - - - - - - - - - - AJAX ERROR! + No Summary Statistics... + + - - There was an error loading the status of processes. Please make sure that CWS is up and - running. - + + + + + Name + Key + Version + Workers + Status + Instance Statistics + + + + + - - - - - - - - + + + thisModelJson["model-name"] = modelName; + thisModelJson["model-id"] = modelId; + thisModelJson["version"] = version; + thisModelJson["status"] = status; + thisModelJson["has-assigned-workers"] = hasAssignedWorkers; + thisModelJson["stat-proc-pending"] = statPending; + thisModelJson["stat-proc-disabled"] = statDisabled; + thisModelJson["stat-proc-running"] = statActive; + thisModelJson["stat-proc-completed"] = statCompleted; + thisModelJson["stat-proc-error"] = statError; + thisModelJson["stat-proc-failed-to-start"] = statFailedToStart; + thisModelJson["stat-proc-incident"] = statIncident; + + models[modelId] = thisModelJson; + + }); + jsonFile["models"] = models; + $.fn.dataTable.fileSave( + new Blob([JSON.stringify(jsonFile)]), + 'deployments_export.json' + ); + } + + +
Your browser has been idle for more than 10 minutes. Do you want to resume?
Are you sure you want to delete process definition ''?
Warning: All data for this process definition will be removed (run history, logs, pending - runs, etc...)
There was an error deleting process definition ''. -
This is because all manual tasks (i.e. User Tasks and manual process starts via the - TaskList app) - are initiated via this worker.
There was an error loading the status of processes. Please make sure that CWS is up and - running.