Building a Real IBM UrbanCode Deploy Plugin – Part 3: Groovy

After we have set up the XML files, the next step is the Groovy scripts that will drive the activity. The XML files specify the parameters that will be sent to the Groovy script, how the script will be launched, and even how the return values from the script will be handled. So the scripts job then becomes about grabbing the parameters, doing its job, and then terminating in a predictable way.

For this cut of our Liquibase project, the scripts are effectively command line wrappers. So their job is relatively simple – reliably launch Liquibase via its command line and return the results. For a first cut, we can exploit the fact that the Liquibase command line consistently takes certain parameters and use a common script as a basis for all the commands we want to control and just tweak each as needed for the individual commands. There is ample room for refactoring, but this pattern works pretty well and is quick to implement for our example.

The target command line we are working with in this example step is to use Liquibase to automatically generate some documentation for our database.  In this case the database in question is the one included with the ‘JPetStore’ sample application that comes with IBM UrbanCode Deploy.  If we were going to run the command in a shell, the command would look like it appears below.  We want to duplicate this command with our Groovy script.

/opt/liquibase/liquibase --driver=com.mysql.jdbc.Driver --classpath=/opt/mysql-connector-java-5.0.8-bin.jar --url=jdbc:mysql://localhost:3306/jpetstore --username=exampleuser --password=**** --changeLogFile=/opt/dbinfo/jpetstore_base.xml dbDoc /opt/dbinfo/jpetstore

The first bit of the code is just to get the input properties that are passed in from the agent when the script is fired.

def workDir = new File('.').canonicalFile
final def props = new Properties()
final def inputPropsFile = new File(args[0])
try {
 inputPropsStream = new FileInputStream(inputPropsFile)
catch (IOException e) {
 throw new RuntimeException(e)

We then pull the properties out into individual variables. This list maps 1:1 with the <property> elements we created in plugin.xml.

def command = props['command']
def driver = props['driver']
def driverClasspath = props['driverClasspath']
def jdbcURL = props['jdbcURL']
def username = props['username']
def password = props['password']
def changeLogFile = props['changeLogFile']
def docOutDir = props['docOutDir']

Then, we do simple string manipulation to build the command string that will be passed to the shell.

def lqcmd = command + " " 
lqcmd = lqcmd + "--driver=" + driver + " " 
lqcmd = lqcmd + "--classpath=" + driverClasspath + " " 
lqcmd = lqcmd + " --url=" + jdbcURL + " " 
lqcmd = lqcmd + "--username=" + username + " " 
lqcmd = lqcmd + "--password=" + password + " " 
lqcmd = lqcmd + "--changeLogFile=" + changeLogFile + " "
lqcmd = lqcmd + "dbDoc " 
lqcmd = lqcmd + docOutDir

Finally, we execute the command in the shell and wait for the command to complete. All this basic example checks for is a non-zero exit value otherwise it reports success. This could, of course, be made more robust if needed.

def proc = lqcmd.execute()
proc.waitForProcessOutput(System.out, System.out)

if (proc.exitValue() != 0) {
 System.exit proc.exitValue()

This pattern is then repeated in the other .groovy files referenced by plugin.xml with variances in the properties mapping (some have more or less parameters than this one) and from that the command line construction. Remember to be sure that the name of the file matches what is in your plugin.xml file exactly. Put the XML files and Groovy scripts all together into a ZIP file like we saw in Part 1 and import that ZIP into your IBM UrbanCode Deploy server.  At that point it should show up in your process designer tool in UrbanCode Deploy and you or your teams are ready to control a Liquibase installation using the graphical process design and automation capabilities of the tool.

Tagged with: , , , , , , , , ,
Posted in DevOps, HowTo, UrbanCode Deploy

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s


Avnet Services DevOps Team Blog

Crossing Silos

DevOps only works if you cross boundaries

Avnet Services DevOps

Avnet Services DevOps Team Blog

%d bloggers like this: