/ Management  

Stop wasting time; Instantly create an organization (incl. service containers and DSO) with automation

Hi there “Process Automation” fans,

Welcome to a new installment of “Process Automation” tips.

I see it sooooo often with customers. All the manual steps to put an OPA organization up and running. Boy-o-Boy…Why all the pain? Why all that time-wasting? Why doing all the error-prone steps manually?…With a platform full of services, you’ll expect to do one thing properly; That’s “AUTOMATION”! There is a reason our beloved platform calls it “Process Automation”!?!? So, why are we not doing it? Do we not know how? Do we not want to invest time understanding the concepts? Do we stick our heads in the sand and wait until somebody tells them to wake up? Well, here is your wake-up call…

For this post we’ll automate the creation of these steps:

  • Create a brand-new organization (I leave OTDS for user/group consolidation out-of-scope, but it has an API (http://192.168.56.107:8181/otdsws/api/index.html) to automate here as well)
  • Create service groups
  • Create service containers
  • Stop/Start/Restart service containers (which I leave for next week to keep you awake!)
  • Create a Data Source Object (DSO) for connecting to an external database and extracting linked Entities; Read here and here
  • Delete an organization (with the organization deletion Tool) because we also want to clean up our mess properly

This is a list of use-cases why you want to have these specific automation-steps in place:

  • When a developer gets stuck in his organization with corrupted data and require a re-“initialization”.
  • Cleaning an organization from garbage (In Dev/Test/Acp); Can happen after an upgrade, and you want to prepare yourself for the next upgrade.
  • A fresh installation and creating a similar structure repeatedly.
  • A “Build” organization for package generation/deployment. From a developer perspective, you can’t have enough organizations available. Each developer needs its own, you want a “build” organization, and you want a “deploy” organization for your first tests.

When you want to go next level with CI/CD, read these articles


Let’s get right into it…

A note upfront: You see me using CLI calls with the CWS tool, and this is one way to automate things! The other way of automating things is simply watching the developer tools of Chrome browser, run the actions once by hand, and recording all the calls. Once all information is available, you can execute these services from an external tool like SoapUI or Postman. The only thing you require is a session, but that’s all explained here.

Comment me if you want a post about how to do this post with direct service calls from SoapUI…It’ll be great as well!


Organization creation

Let’s get our hands dirty…Is your VM up and running? Yes? Jump into the ‘/system’ shared organization where we can create new organizations (with your sysadmin account!). With the developer tools open in your browser, you can create an organization from the ‘Organization Manager’ artifact. After you’re done, you found yourself a SOAP call looking like this:

1
2
3
4
5
6
7
8
9
10
11
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP:Body>
<CreateOrganization xmlns="http://schemas.cordys.com/1.0/organization">
<Name>opa_build</Name>
<DisplayName>OPA Tips Build</DisplayName>
<Administrators>
<UserName>sysadmin</UserName>
</Administrators>
</CreateOrganization>
</SOAP:Body>
</SOAP:Envelope>

The response for this call has an element <ID>3</ID>. This is the unique ID (or ‘destinationindicator’) for our organization (see here). It’s an important ID as all tables in the database start with this ‘OrgID’ (o3 in my case)

We can also delete an organization here (if you didn’t use it yet!). However, you will not find a DeleteOrganization service call! This will be a DeleteRecursive call in the category Method Set LDAP 1.0. It’s not for now as we’ll learn about the ‘organizationremovaltool’ (you can find more details here already if your curious!)


Service group/container creation

This step we’ll do differently. We could still watch the developer tools, open the ‘System Resource Manager’ in our brand-new organization, and create a new service container. Only, this makes an advanced Update call to CARS (our OpenLDAP instance) with subtasks/tuples/entries for creating a ‘serviceGroup’, a ‘serviceContainer’, and a ‘connectionPoint’. Exactly what you would fill in for all the steps of the normal service container creation wizard…Can we do better? Yes, please…

For this, we do a quick recap on one of our CI/CD posts about ANT-tasks where an interesting JAR-file (anttasks.jar) passes by. A little decompiling teaches us not only about the already familiar deployapplicationpackage and undeployapplicationpackage operations, but more is exposed on operations like createconnectionpoint, createdatabaseconfiguration, createservicegroup, and createservicecontainer. These also have a “Delete”-variant!

automate_001

You can also double-check the administration guide of the platform in section “Application Package Deployment utility”, but this post exposes new examples and undocumented thinking.

Time to get our hands dirty…again, but this time on the server (mine is RHEL). We first need to install “Apache Ant” with this command: sudo yum install -y ant. Once done, you can validate with ant -version.

Next is setting some environment variables:

1
2
3
4
5
6
7
8
9
10
export CORDYS_HOME=/opt/opentext/ProcessAutomationCE/defaultInst
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
export PATH=$PATH:$CORDYS_HOME/bin
export CLASSPATH=$CLASSPATH:$CORDYS_HOME/cordyscp.jar
export JAVACMD=$JAVA_HOME/bin/java
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$JAVA_HOME/lib/server:$CORDYS_HOME/lib
#You need this JPDA entry to remote debug your ANT calls in your IDE (if required).
#The flag 'suspend=y' makes sure it'll wait till you connect from your IDE!
#Comment me below this post if you don't have a clue what I'm talking about.
export ANT_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005"

I already have a sysadmin account on my RHEL VM during installation…A thing I always recommend doing. Installing the platform with a different account always requires additional security steps to make later in the process. The platform simply likes sysadmin for some reason!

Now we can create a build.xml file with vi ~/build.xml pasting in content like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<project basedir="." default="testAll" name="Test-Antscripts">
<!-- Run tests based on these properties -->
<property file="test.properties"/>
<!-- Add the task definition to include the custom tasks -->
<property environment="env"/>
<property name="bop.install.dir" value="${env.CORDYS_HOME}"/>
<path id="anttask.classpath">
<pathelement location="${bop.install.dir}/components/anttasks/anttasks.jar"/>
</path>
<taskdef resource="com/cordys/deployment/ant/taskdef.xml">
<classpath refid="anttask.classpath"/>
</taskdef>
<!-- call the tests -->
<target name="info">
<echo>${bop.install.dir}/components/anttasks/anttasks.jar</echo>
<echo>Java/JVM version: ${ant.java.version}</echo>
<echo>Java/JVM detail version: ${java.version}</echo>
<echo>SERVER: ${cordys.server}</echo>
</target>
<target name="testAll">
<antcall target="testCreateServiceGroup"/>
<antcall target="testCreateServiceContainer"/>
<antcall target="testCreateConnectionPoint"/>
<antcall target="testDeleteConnectionPoint"/>
<antcall target="testDeleteServiceContainer"/>
<antcall target="testDeleteServiceGroup"/>
</target>
<target name="testCreateServiceGroup">
<!--This is an example for a new 'WS-App Server' type of container
<createservicegroup name="sg_wsappserver" organization="opa_build" ldapRoot="cn=cordys,cn=defaultInst,o=25.1.com">
<WebserviceInterface name="cn=WS-AppServer Development Method Set,cn=Cordys WS-AppServer" namespace="http://schemas.cordys.com/WS-AppServerDevelopment/1.0" />
</createservicegroup>
-->
<createservicegroup name="sg_appserver" organization="opa_build" ldapRoot="cn=cordys,cn=defaultInst,o=25.1.com">
<WebserviceInterface name="cn=OrgModel Method Set,cn=OpenText Identity" namespace="http://schemas.cordys.com/orgmodel/runtime/OrgModel/1.0"/>
<!--Add additional 'WebserviceInterface' lines if applicable-->
</createservicegroup>
</target>
<target name="testDeleteServiceGroup">
<deleteservicegroup organization="opa_build" name="sg_appserver" ldapRoot="cn=cordys,cn=defaultInst,o=25.1.com"/>
</target>
<target name="testCreateConnectionPoint">
<!--This is an example for a new 'WS-App Server' type of container
<createconnectionpoint name="cp_wsappserver" organization="opa_build" ldapRoot="cn=cordys,cn=defaultInst,o=25.1.com" server="opa" servicecontainerName="sc_wsappserver" servicegroupName="sg_wsappserver"/>
-->
<createconnectionpoint name="cp_appserver" organization="opa_build" ldapRoot="cn=cordys,cn=defaultInst,o=25.1.com" server="opa" servicecontainerName="sc_appserver" servicegroupName="sg_appserver"/>
</target>
<target name="testDeleteConnectionPoint">
<deleteconnectionpoint organization="opa_build" name="cp_appserver" servicecontainerName="sc_appserver" servicegroupName="sg_appserver" ldapRoot="cn=cordys,cn=defaultInst,o=25.1.com"/>
</target>
<target name="testCreateServiceContainer">
<!--This is an example for a new 'WS-App Server' type of container
<createservicecontainer osProcess="Application Server" ldapRoot="cn=cordys,cn=defaultInst,o=25.1.com" name="sc_wsappserver" organization="opa_build" server="opa" servicegroupName="sg_wsappserver" startUpType="true">
<applicationConnector implementation="com.cordys.cpc.bsf.connector.BsfConnector" htmlfile="wcp/admin/applicationconnector/applicationserverconnectorproperties.htm" configurationFile="/home/sysadmin/sc_wsappserver_config.xml"/>
</createservicecontainer>
-->
<createservicecontainer osProcess="Application Server" ldapRoot="cn=cordys,cn=defaultInst,o=25.1.com" name="sc_appserver" organization="opa_build" server="opa" servicegroupName="sg_appserver" startUpType="true">
<!--The implementation class depends on the type of container!-->
<applicationConnector implementation="com.cordys.applicationserverconnector.Connector" htmlfile="wcp/admin/applicationconnector/applicationserverconnectorproperties.htm" configurationFile="/home/sysadmin/sc_appserver_config.xml"/>
</createservicecontainer>
</target>
<target name="testDeleteServiceContainer">
<deleteservicecontainer organization="opa_build" servicegroupName="sg_appserver" name="sc_appserver" ldapRoot="cn=cordys,cn=defaultInst,o=25.1.com"/>
</target>
</project>

There is a reference to a test.properties file. Create it (vi ~/test.properties) with this content (smartly with your environment specifics!):

1
2
3
4
#General properties
cordys.server=opa
cordys.ldaproot=cn=cordys,cn=defaultInst,o=25.1.com
cordys.failonerror=true

For your reference; My hostname (FQDN) is: opa.25.1.com

You also see a reference to a sc_appserver_config.xml file. Create it (vi ~/sc_appserver_config.xml) with this content:

1
2
3
4
5
6
<configuration>
<!--The regular documentation does not tell you about this classpath element!-->
<classpath>
<location>components/applicationserverpackage/applicationserverpackage.jar</location>
</classpath>
</configuration>

You also see a reference to a sc_wsappserver_config.xml file which will have this content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<configuration>
<!--The regular documentation does not tell you about this classpath element!-->
<classpath>
<location>components/wsappserver/wsappserver.jar</location>
<location>components/ruleengine/ruleengine.jar</location>
</classpath>
<startupDependency>
<namespace>http://schemas.cordys.com/1.0/xmlstore</namespace>
</startupDependency>
<ruleEnabled>false</ruleEnabled>
<auditEnabled>off</auditEnabled>
<initializeDB>false</initializeDB>
<multiTenant>false</multiTenant>
<initializeEIS>false</initializeEIS>
<customInitializer/>
<applicationInitializer/>
<autoCleanup>false</autoCleanup>
</configuration>

Where do we gain all this knowledge on those <configuration> XML parts? Well, first creating things by hand in the UI and watching closely what will eventually land in the ‘LDAP Explorer’ artifact:

automate_002

Now you can move to the location of those two new files (cd ~) and run this first command: ant info. It will output the details of the info target of our XML configuration:

1
2
3
4
5
6
7
8
9
10
Buildfile: /home/sysadmin/build.xml

info:
[echo] /opt/opentext/ProcessAutomationCE/defaultInst/components/anttasks/anttasks.jar
[echo] Java/JVM version: 17
[echo] Java/JVM detail version: 17.0.14
[echo] SERVER: opa

BUILD SUCCESSFUL
Total time: 0 seconds

Yes…It’s magic; Notify yourself also of the possible variables you can pass in via the properties file!

Our next step is calling: ant testCreateServiceGroup

Aiiii, an expected error (because we created this one manually already for R&D):
The DN cn=sg_appserver,cn=soap nodes,o=opa_build,cn=cordys,cn=defaultInst,o=25.1.com already exists on the LDAP server.

Remove it from the UI, makes the second call is a success! 🥳

For automation, you want to check this DN value (from my error) with a SOAP call like GetLDAPObject (in Method Set LDAP 1.0) OR you add an extra flag in the build XML override="true"

What we can create, we can also remove: ant testDeleteServiceGroup

Be aware this will also remove the service containers within! I also recommend to first remove the service containers, then remove the service group…It just feels better!

Make sure these all work before running the ultimate test (incl. the clean/deletions where applicable for you):

1
2
3
4
5
6
7
ant info
ant testCreateServiceGroup
ant testCreateServiceContainer
ant testCreateConnectionPoint
ant testDeleteConnectionPoint
ant testDeleteServiceContainer
ant testDeleteServiceGroup

Your final test call will be ant testAll! The result is…NOTHING, as we clean everything! This is my output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Buildfile: /home/sysadmin/build.xml

testAll:

testCreateServiceGroup:
[createservicegroup] 11:04:58 : Service Group sg_appserver created successfully.

testCreateServiceContainer:
[createservicecontainer] 11:04:58 : Service Container sc_appserver created successfully.

testCreateConnectionPoint:
[createconnectionpoint] 11:04:59 : Connection Point cp_appserver created successfully.

testDeleteConnectionPoint:
[deleteconnectionpoint] 11:04:59 : Connection Point cp_appserver deleted successfully.

testDeleteServiceContainer:
[deleteservicecontainer] 11:04:59 : Service Container sc_appserver deleted successfully.

testDeleteServiceGroup:
[deleteservicegroup] 11:04:59 : Service Group sg_appserver deleted successfully.

BUILD SUCCESSFUL
Total time: 3 seconds

DSO creation

What we can do for service groups and service containers, we can also do for a Data Source Object. It’s nothing more than a database connection setup for reusability in any of your service containers (like a WS-AppServer container which can extract ‘Linked’ entities from a DB; Read about it here)

For a new DSO, we can simply extend our build.xml with these snippets:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<project basedir="." default="testAll" name="Test-Antscripts">
...
<target name="testAll">
...
<antcall target="testCreateDSO"/>
<antcall target="testDeleteDSO"/>
...
</target>
...
<target name="testCreateDSO">
<!--The regular documentation does not show you this example, but it's straight forward!-->
<createdatabaseconfiguration name="Cordys DSO" server="opa" organization="opa_build" ldapRoot="cn=cordys,cn=defaultInst,o=25.1.com">
<driver dbVendor="PostgreSQL" dbConnectorType="JDBC" connectionString="jdbc:postgresql://opa.25.1.com:5432/opa_db"/>
<database defaultDatabaseName="opa_db" dbUserName="postgres" dbPassword="admin"/>
</createdatabaseconfiguration>
</target>
<target name="testDeleteDSO">
<deletedatabaseconfiguration organization="opa_build" name="Cordys DSO" server="opa" ldapRoot="cn=cordys,cn=defaultInst,o=25.1.com"/>
</target>
...
</project>

You can evaluate them with these calls:

1
2
ant testCreateDSO
ant testDeleteDSO

Does it work? Well, watch this valid connectivity test:

automate_003


Delete organization

Finally, the last part of the post…Deleting an organization! Not via the ‘Organizational Manager’ artifact, but solidly following our own post.

These are the quick steps:

  1. Deploy the tool Cordys Organization Removal Tool in the ‘/system’ space with the ‘Application Deployer’ artifact (mine is already deployed in OPA version 25.3).
  2. Run this command: sh /opt/opentext/ProcessAutomationCE/defaultInst/components/organizationremovaltool/organizationremovaltool.sh opa_build

The outcome is a party again! 🤠

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Preparing to execute organization data cleanup for all components.
Deleting the content for Cordys CAP
Skipping action for handler :com.cordys.bam.organizationremoval.ApplicationDataRemover. Probably the application corresponding to the missing handler class is not installed.
Skipping action for handler :com.cordys.bam.organizationremoval.RepositoryDataRemover. Probably the application corresponding to the missing handler class is not installed.
Skipping action for handler :com.cordys.mdm.organizationremovaltool.MDMOrganizationContentRemovalHandler. Probably the application corresponding to the missing handler class is not installed.
Deleting the content for Cordys BPM
Deleting the content for Cordys Case
Deleting the content for Cordys Data Transformation
Deleting the content for Cordys COBOC
Deleting the content for Cordys Scheduler
Deleting the content for Cordys Notification
Deleting the content for Cordys Rule
Deleting the content for Cordys Collaborative Workspace
Removing spaces from organization: opa_build
No spaces were found to be removed.
Removing the space(s) has completed.
Deleting the content for Cordys Tag Server
Deleting the content for Cordys Task Service
Deleting the content for Cordys Web Content
Deleting the content for Cordys Service Containers
Deleting the content for Cordys Log
Deleting the content for Cordys WS-AppServer
Deleting the content for Cordys XMLStore
Deleting the content for Cordys LDAP
Deleting the content for Cordys Audit
Organization data cleanup is completed for all components.
Organization removal tool execution is completed and is exiting.

Nicely “DONE” with a first impression of what we can all automate with the CLI tool of our beloved platform. For the people thinking it’s impossible…Automation is always possible, but you just need someone to tell you with a little guidance to improve your way of thinking. No problem…It’s hereby done, and it’s an action for you to start automating all the rest of your time-wasting steps. Have a great weekend and till next week for another great topic about “Process Automation Tips”! 🍹

Don’t forget to subscribe to get updates on the activities happening on this site. Have you noticed the quiz where you find out if you are also “The Process Automation guy”?