/ Development  

Deploy your solution with ANT tasks

Hi there AppWorks fans,

Welcome to a new installment of AppWorks tips.

With this post we continue the series of posts where want to learn about Continuous Deployment and Continuous Integration (CD/CI) on our AppWorks platform. A hot topic and required to have some knowledge on it. Last week we covered the CLI command to build a package and this week we focus on Ant-tasks that will deploy the package for us. When we have both CLI and Ant in place we can further automate the steps with Jenkins in the next week…Have fun! 💪


Let get right into it…

I assume you have your environment up and running and that you’ve created a .CAP package with last week’s CLI commands and saved it somewhere separately. Why is that? because the last command in our CLI commands batch is to remove the workspace so our build organization is clean again. When you remove the workspace you also drop that CAP file…So that’s why we move it elsewhere!

Let’s grab the ‘Administration Guide’ and go to the section about ‘Application Package Deployment utility’ or do a search for ‘Ant’. This manual tells us about some special ‘AppWorks’ specific Ant tasks that can do a deployment for us with the fancy name ‘deployapplicationpackage’…Yeah…that’s what we want!

But before we can start…


Make ‘Ant’ available on our VM machine

That’s the same machine where our platform is installed.

Just install with this command from your MobaXTerm client…clean and steady: sudo yum install -y ant

And see if the installation is done with ant -version

1
Apache Ant(TM) version 1.9.4 compiled on November 5 2018

“DONE”…next…


Create a new Unix account

This new account must match the user account that is used in AppWorks and must also have the ‘setupUser’ role applied in AppWorks!

ant_000

We first start our deployment in the ‘shared’ space with this ‘sysadmin’ account.

Add that user with sudo useradd sysadmin

Give it a password with sudo passwd sysadmin

Let’s also give it ‘sudo’ permission sudo usermod -aG wheel sysadmin

And now make a new session with this account…All the following commands will be done with this account!!


Set some environment variables

I set these variable for that new ‘sysadmin’ account and will also run the tasks with that account. The CLI commands were executed with the root account, but for these Ant tasks it’s important to run them with an account that is available in our LDAP instance (= CARS/OpenLDAP)!

So, login with ‘sysadmin’ on your MobaXTerm client and set these variables:

1
2
3
4
5
6
export CORDYS_HOME=/opt/opentext/AppWorksPlatform/defaultInst
export PATH=$PATH:$CORDYS_HOME/bin
export CLASSPATH=$CLASSPATH:/opt/opentext/AppWorksPlatform/defaultInst/cordyscp.jar
export JAVACMD=/usr/lib/jvm/java-11-openjdk/bin/java
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/jvm/java-11-openjdk-11.0.6.10-1.el7_7.x86_64/lib/server:/opt/opentext/AppWorksPlatform/defaultInst/lib

JAVACMD and JAVA_HOME is set because I have java 8 and 11 and we explicitly need version 11, as the platform is installed with Java 11; otherwise you get some Java compiler version mismatch errors.

/opt/opentext/AppWorksPlatform/defaultInst/lib/ contains a lib called libxmlForJava.so that is required!


Crafting the Ant build file

We start with just the sample from the documentation that looks like the below 2 files. I saved them in the home folder on my VM under ‘/home/sysadmin’

build.xml content (that is slightly changed with an ‘info’ target element for test purposes)

vi build.xml

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
<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>PORT: ${cordys.port}</echo>
<echo>SERVER: ${cordys.server}</echo>
</target>
<target name="testAll">
<antcall target="testApplicationPackageDeploy"/>
<antcall target="testApplicationPackageUndeploy"/>
</target>
<target name="testApplicationPackageDeploy">
<deployapplicationpackage buildNumber="${cordys.buildnumber}" failonerror="${cordys.failonerror}" ldapRoot="${cordys.ldaproot}" name="${cordys.applicationpackagename}" port="${cordys.port}" protocol="${cordys.webprotocol}" revertOnfailure="${cordys.revertonfailure}" server="${cordys.server}" timeout="${cordys.timeout}" version="${cordys.version}" webserver="${cordys.webserver}"/>
</target>
<target name="testApplicationPackageUndeploy">
<undeployapplicationpackage failonerror="${cordys.failonerror}" ldapRoot="${cordys.ldaproot}" name="${cordys.applicationpackagename}" server="${cordys.server}"/>
</target>
</project>

test.properties content (that is changed for my environment settings)

vi test.properties

This file is referenced in the build.xml!

1
2
3
4
5
6
7
8
9
10
11
12
13
#General properties.
cordys.server=win-5skkmburvo7
cordys.ldaproot=cn=cordys,cn=defaultInst,o=mydomain.com
cordys.failonerror=true
#Package Deployment properties
cordys.webserver=192.168.56.107
cordys.webprotocol=http
cordys.port=8080
cordys.applicationpackagename=My Company AW_CD_CI_PROJECT
cordys.timeout=30000
cordys.revertonfailure=true
cordys.version=1.0
cordys.buildnumber=0
  • Don’t use an IP for ‘cordys.server’ (Not working…I tried!)
  • Make sure your ‘ldaproot ‘points to the correct location. You can find it with the CMC tool.

ant_001

  • Make sure the version number and build number match the package (you can find this in the name of the .CAP file itself, but if you open the manifest.xml in that .CAP file (after you downloaded it from the server) you can also find it there also).

    ant_002

  • And that is the same for that ‘applicationpackagename’ variable where you need to use the name that matches the package name in the packaging properties. See the screenshot above!…That is also without the .cap extension!!

Now go to build directory with cd /home/sysadmin and give the command ant info

This will be the output (for my environment):

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

info:
[echo] /opt/opentext/AppWorksPlatform/defaultInst/components/anttasks/anttasks.jar
[echo] Java/JVM version: 1.9
[echo] Java/JVM detail version: 11.0.6
[echo] PORT: 8080
[echo] SERVER: win-5skkmburvo7

BUILD SUCCESSFUL
Total time: 0 seconds

If you see this message [taskdef] Could not load definitions from resource com/cordys/deployment/ant/taskdef.xml. It could not be found. you need to make a security change for that ‘anttasks.jar’ file. On my image a see that not all subfolder/files in the ‘components’ folder have the same permission for some reason…This will fix it sudo chmod 777 -R /opt/opentext/AppWorksPlatform/defaultInst/components/

This happened to me on the ‘Logs’ directory too…fix: sudo chmod 777 -R /opt/opentext/AppWorksPlatform/defaultInst/Logs/

Same on the ‘config’ directory: sudo chmod 777 -R /opt/opentext/AppWorksPlatform/defaultInst/config/

And sudo chmod 777 -R /opt/opentext/AppWorksPlatform/defaultInst/certificates/

And sudo chmod 777 -R /opt/opentext/AppWorksPlatform/defaultInst/localization/

Before we do a deploy…Make sure the .CAP package is available in /opt/opentext/AppWorksPlatform/defaultInst/capcontent/packages/shared/My Company AW_CD_CI_PROJECT/. And give it the correct name convention…See the next copy command!

But first create that folder with the correct permissions:

1
2
sudo mkdir /opt/opentext/AppWorksPlatform/defaultInst/capcontent/packages/shared/My\ Company\ AW_CD_CI_PROJECT
sudo chown tomcat:tomcat /opt/opentext/AppWorksPlatform/defaultInst/capcontent/packages/shared/My\ Company\ AW_CD_CI_PROJECT

Last time I saved it the home folder of ‘otadmin’ so the command to copy the package will look like this sudo cp /home/otadmin/My\ Company\ AW_CD_CI_PROJECT\ 1.0.0.cap /opt/opentext/AppWorksPlatform/defaultInst/capcontent/packages/shared/My\ Company\ AW_CD_CI_PROJECT/ver1.0build0.cap

And we’ll also update some permissions on that package

1
2
sudo chown tomcat:tomcat /opt/opentext/AppWorksPlatform/defaultInst/capcontent/packages/shared/My\ Company\ AW_CD_CI_PROJECT/ver1.0build0.cap
sudo chmod 664 /opt/opentext/AppWorksPlatform/defaultInst/capcontent/packages/shared/My\ Company\ AW_CD_CI_PROJECT/ver1.0build0.cap

It’s important to have that naming convention of that .cap file correct!…Match it with the information from the manifest.xml you saw before!

Those weird slashed in my original package are there to escape all the spaces in the package name!

Now for our first deployment…let’s run with ant testApplicationPackageDeploy

If you get an the error ‘The signature of the package ‘My Company AW_CD_CI_PROJECT 1.0’ is invalid.’ you need to loosen up the package signing options in the ‘Security Administration’ artifact in the ‘system’ organization to make it an ‘allowed’ package!

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

testApplicationPackageDeploy:
[deployapplicationpackage] 10:42:18 : Application Package deployed successfully.

BUILD SUCCESSFUL
Total time: 36 seconds

Let’s double check that result by opening our build URL in administration mode: http://192.168.56.107:8080/home/appworks_tips_build/app/admin

Update the space location to ‘shared’ and let the light shine upon us…Hallelujah!! 👼

ant_003

And for an un-deployment run ant testApplicationPackageUndeploy

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

testApplicationPackageUndeploy:
[undeployapplicationpackage] 10:43:46 : Application Package undeployed successfully.

BUILD SUCCESSFUL
Total time: 18 seconds

Finally for the full run with ant where it will pick up the default ‘testAll’ target which will do a deploy and undeploy task!

That’s a ‘DONE’ for the shared space…next…


Deployment in our ‘build’ organization

For this we’ll update our ‘test.properties’ for with an extra parameter:

cordys.organization=appworks_tips_deploy

Update the deployapplicationpackage and testApplicationPackageUndeploy task with an extra attribute at the end where we use the parameter from the ‘test.properties’.

1
<deployapplicationpackage buildNumber="${cordys.buildnumber}" failonerror="${cordys.failonerror}" ldapRoot="${cordys.ldaproot}" name="${cordys.applicationpackagename}" port="${cordys.port}" protocol="${cordys.webprotocol}" revertOnfailure="${cordys.revertonfailure}" server="${cordys.server}" timeout="${cordys.timeout}" version="${cordys.version}" webserver="${cordys.webserver}" organization="${cordys.organization}" />
1
<undeployapplicationpackage failonerror="${cordys.failonerror}" ldapRoot="${cordys.ldaproot}" name="${cordys.applicationpackagename}" server="${cordys.server}" organization="${cordys.organization}" />

Let’s do a run ant testApplicationPackageDeploy

Let’s double check here: http://192.168.56.107:8080/home/appworks_tips_deploy/app/admin

And there it is…It the ‘organizational’ space…YES!

ant_004

Now for the un-deployment: ant testApplicationPackageUndeploy

Looks fine…correct?

Now for a final conclusion as we saw that we could easily switch between ‘shared’ or ‘organization’, but this all has to do with the package properties we did in design time from our previous post. Look again in the manifest.xml within the .cap package. You can clearly see that our package is configured for both spaces!

ant_005


Log settings (when ^%*^% hits the fan!)

Edit the log configuration file on the server: sudo vi /opt/opentext/AppWorksPlatform/defaultInst/config/Log4jConfiguration.xml

And a new ‘category’ tag before the ‘root’ tag!

1
2
3
4
5
6
7
8
<category name="com.cordys.deployment.ant">
<priority value="debug"/>
</category>
<root>
<priority value="error"/>
<appender-ref ref="file"/>
<appender-ref ref="dbappender"/>
</root>

That ‘root’ tag is for all the platform logging…You can also put that on ‘debug’ level, but that might be some overkill off logging statements!

After this change (no restart needed!) you will see your messages via: sudo tail -f /opt/opentext/AppWorksPlatform/defaultInst/Logs/Launcher.xml

And: sudo tail -f /opt/opentext/AppWorksPlatform/defaultInst/Logs/Application_Server.xml

What I saw in the logging was this URL request where the package is getting downloaded from the server…nice to know! http://http://192.168.56.107:8080/com.cordys.web.cap.DownLoadCAP.wcp?capName=MyCompanyAW_CD_CI_PROJECT&capVersion=ver1.0build0

One other nice thing I learned during this post is searching for a certain class file in a JAR library. Why? Because before all my actions were passed I also hit a lot of @#$%#@# on my fan! And when that is happening you only friend are the debug log settings and the stack tracing that it spits out. This is the command that finds the class ‘LDAPAttributeSet.class’ through a set of JAR files: sudo find /opt/opentext/AppWorksPlatform/defaultInst/ -type f -name '*.jar' -print0 | xargs -0 -I '{}' sh -c 'jar tf {} | grep LDAPAttributeSet.class && echo {}'. I just placed an item on the backlog to tell you more about this feature on how to deep dive a stack trace…Nice stuff!


Well, my dear AppWorks friends…It was a hard one to make it all work this time, but we did it and it was well worth the time…Deploying a .CAP package with the AppWorks platform provided ANT tasks. We only did a deploy and un-deploy, but you’ll find that the administration guide has much more to offer on these tasks like creating service groups and service containers. But with this post you now also know how to call those tasks and continue your journey on the CD/CI topic. I see you in the next post where we will start with Jenkins to craft our first automatic deployment.

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 AppWorks guy”?