Thursday, March 29, 2018

Using Ant to Deploy Automation Scripts

Introduction

I am a firm believer in deploying from source control.  The only thing that should end up in a production environment should come from the source control system.  This is the best way of knowing what is in production and the best way to know that your source is up to date.

It's relatively easy to set up a process to deploy Java changes to Maximo from code taken from the source control system.  Automation scripting makes this harder.  Scripts can be written from within Maximo and some cut & paste process can be used to copy changes to a file that's under source control with Migration Manager moving the changes from one environment to another.  The problem is making sure the script in Maximo is the same as the one in source control.  Any manual process to keep the two files in sync will be error prone and Migration Manager will only propagate that error through the environments.

Using an ant script and some Enterprise Services, I have managed to automate deploying Automation scripts to Maximo.

Create External System

In Maximo, create an External System.  I called mine CONFIG.  Make it use the MXXMLFILE endpoint, or create your own XML file endpoint.

Duplicate the DMLAUNCHPOINT and DMSCRIPT Obejct Structures.  I called mine IS_LAUNCHPOINT and IS_SCRIPT.

Create an Enterprise Service for IS_LAUNCHPOINT called ConfigLAUNCHPOINT and another one for IS_SCRIPT called ConfigSCRIPT.  

Also, create Publish Channels for IS_LAUNCHPOINT and IS_SCRIPT.  This makes it easier to extract data.

Associate the Publish Channel and the Enterprise Service created above with the External System created above.  Make sure everything is enabled.

Ant Script

Here is the ant script I created to publish xml files to the Enterprise Services.  You'll need ant-contrib, commons-httpclient, commons-logging and commons-codec jar files.

<project name="DeployXML" default="deploy" basedir=".">
    <description>Deploy Maximo XML files through Enterprise Services</description>

    <taskdef resource="net/sf/antcontrib/antlib.xml" onerror="fail">
        <classpath>
            <pathelement location="ant-contrib.jar"/>
            <pathelement location="commons-httpclient-3.0.1.jar"/>
            <pathelement location="commons-logging-1.0.4.jar"/>
            <pathelement location="commons-codec-1.10.jar"/>
        </classpath>
    </taskdef>

    <property name="deploy.file" value="deploy.properties" />

    <target name="deploy" depends="init" description="Deploy XML files to Maximo.  The files are determined from deploy properties file.">
        <for list="${deploy.list}" param="index">
            <sequential>
                <propertycopy name="temp.name" from="deploy.@{index}.name" override="true"/>
                <propertycopy name="temp.dir" from="deploy.@{index}.dir" override="true"/>
                <propertycopy name="temp.files" from="deploy.@{index}.files" override="true"/>
                <propertycopy name="temp.url" from="deploy.@{index}.url" override="true"/>
                <echo message="Processing @{index} ${temp.name}"/>
                <antcall target="deploy.directory">
                    <param name="service.name" value="${temp.name}"/>
                    <param name="service.dir" value="${temp.dir}"/>
                    <param name="service.files" value="${temp.files}"/>
                    <param name="service.url" value="${temp.url}"/>
                </antcall>                
            </sequential>
        </for>
    </target>

    <target name="deploy.directory">        
        <echo message="Processing ${service.name} ${service.dir}/${service.files}" />
        <for param="file">
            <path>
                <fileset dir="${service.dir}">
                    <filename name="${service.files}"/>
                </fileset>
            </path>
            <sequential>
                <antcall target="deploy.single">
                    <param name="file" value="@{file}"/>
                </antcall>
            </sequential>
        </for>
    </target>
    
    <target name="deploy.single" depends="init.client">
        <echo message="Deploying ${file}"/>
        <postMethod url="${service.url}"  responseDataProperty="response" clientRefId="maximo">
            <file path="${file}" contentType="text/xml;charset=utf-8"/>            
        </postMethod>
        <echo message="${response}"/>
    </target>   

    <target name="init">
        <loadproperties srcFile="${deploy.file}" />
    </target>
    
    <target name="init.client">
        <httpClient id="maximo">
            <clientParams authenticationPreemptive="true"></clientParams>        
            <httpState>
                <credentials username="${maximo.username}" password="${maximo.password}"/>
            </httpState>
        </httpClient>
    </target>
</project>

Property File

Here is the property file.  

maximo.base.url=http://localhost:9080/meaweb/esqueue/CONFIG
maximo.base.directory=C:/Users/developer/workspace/Maximo
maximo.username=username
maximo.password=password

deploy.list=1,2

deploy.1.name=Script
deploy.1.dir=${maximo.base.directory}/Config/
deploy.1.files=**/*ConfigSCRIPT*.xml
deploy.1.url=${maximo.base.url}/IS_ConfigSCRIPT

deploy.2.name=LaunchPoint
deploy.2.dir=${maximo.base.directory}/Config/
deploy.2.files=**/*ConfigLAUNCHPOINT*.xml
deploy.2.url=${maximo.base.url}/IS_ConfigLAUNCHPOINT

Set maximo.base.url to the root url of all Enterprise Services for the External System you created.

Set maximo.username and maximo.password either in the property file or as command line parameters.  This will be a username and password that is allowed to call the Enterprise Services.

Set maximo.base.directory to the top level of your source project.

Set deploy.list to the list of configurations you want deployed.  They will be deployed in the order given.  Each entry is an index to the deploy.x entries below.

Set deploy.x.name to a descriptive name of what will be deployed.  It will be displayed while the ant script runes.

Set deploy.x.dir to a directory in which the files to upload can be found.  This can be a top level directory as shown here.  It really depends on how you want to organize your files.

Set deploy.x.files to a file or files to import into Maximo.  The sample property file will actually look in all subdirectories for file names that contain ConfigScript.  Again, this will depend on how your files are organized.

Set deploy.x.url to the URL of the Enterprise Service that will import the files.

Deploying Automation Scripts

Deploying the automation scripts is simply a matter of running the ant script. 

Once the ant script completes, it's a good idea to check Message Reprocessing in case there were any errors importing the scripts.

You can use this to also deploy workflows.

2 comments:

  1. Can you do this for DbConfig Scripts?
    - Admin Mode On
    - Deploy Scripts
    - Config DB
    - Admin Mode Off

    ReplyDelete
    Replies
    1. Did you want the admin mode scripted or are these manual steps performed by the administrator. Placing Maximo in admin modes turns off a bunch of different things (like event listeners, and crons) that are usually needed or desired while deploying scripts.

      It should be possible to create a custom service that, when posted to, would execute the admin mode on, config db, and admin mode off steps. You'd need a custom user exit to perform those steps, but it shouldn't be difficult.

      Delete