Welcome!

XebiaLabs | Continuous Delivery and Agile DevOps Tools

XebiaLabs Blog

Subscribe to XebiaLabs Blog: eMailAlertsEmail Alerts
Get XebiaLabs Blog via: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


Related Topics: Intel XML, XML Magazine

Blog Feed Post

Creating XL Release Tasks Dynamically Using Jython API

This blog post caters to users who have a good understanding of Tasks in XL Releases and also know how to code in python. It talks about how you can make the best use of enhanced Jython API that has been available since XL Release 4.6.0 to dynamically generate tasks in a phase inside a release during runtime.

Jython API can be used in two different ways in XL Release.

  1. It can be injected as a code snippet into a Script Task and will then be executed when the release execution reaches the Task. This can be thought of as a macro for those who have used MS Excel/Project in the past along with VB Macros.  The only downside of putting code snippets inside a script task is that its fragile, can be easily broken with a single keystroke by mistake and doesn’t give nice appearance with fancy user inputs
  2. The second more fancier way is to properly wrap around your code snippet in a Custom Task and expose the input and output fields in UI Text fields. This provides a better way to encapsulate the code snippet and its much more stable since the inline code logic can’t be tampered with

 

Here’s a Jython code snippet to create both Simple and Custom script tasks with XL Releases. The following two code snippets when directly pasted into a script Task separately and executed would leave to creation of a variety of new tasks in the same phase namely a manual task, notification task, script task, deployit task, webhook and jenkins

 

Simple Tasks with Jython

import sys, string, time
import com.xhaus.jyson.JysonCodec as json
from com.xebialabs.xlrelease.domain import Task
from com.xebialabs.deployit.plugin.api.reflect import Type
from java.text import SimpleDateFormat
 
def createSimpleTask(phaseId, taskTypeValue, title, propertyMap):
    parenttaskType = Type.valueOf(taskTypeValue)
    parentTask = parenttaskType.descriptor.newInstance("nonamerequired")
    parentTask.setTitle(title)
    sdf = SimpleDateFormat("yyyy-MM-dd hh:mm:ss")
    for item in propertyMap:
        if item.lower().find("date") > -1:
            if propertyMap[item] is not None and len(propertyMap[item]) != 0:
                parentTask.setProperty(item,sdf.parse(propertyMap[item]))
        else:
            parentTask.setProperty(item,propertyMap[item])
    taskApi.addTask(phaseId,parentTask)
 
createSimpleTask(phase.id,"xlrelease.Task", "this is cool", {'description':'coolio'})
createSimpleTask(phase.id,"xlrelease.NotificationTask", "this is the title", {'description':'this is the description'})
createSimpleTask(phase.id,"xlrelease.ScriptTask", "this is the title", {'description':'this is the description'})
createSimpleTask(phase.id,"xlrelease.DeployitTask", "this is the title", {'description':'this is the description','server':'localhost'})

 

Custom Script Tasks with Jython

import sys, string, time
import com.xhaus.jyson.JysonCodec as json
from com.xebialabs.xlrelease.domain import Task
from com.xebialabs.deployit.plugin.api.reflect import Type
from java.text import SimpleDateFormat
def createScriptBasedTask(phaseId,taskTypeValue,title,precondition, propertyMap):
    parenttaskType = Type.valueOf("xlrelease.CustomScriptTask")
 
    parentTask = parenttaskType.descriptor.newInstance("nonamerequired")
    parentTask.setTitle(title)
 
    childTaskType = Type.valueOf(taskTypeValue)
    childTask = childTaskType.descriptor.newInstance("nonamerequired")
    for item in propertyMap:
        childTask.setProperty(item,propertyMap[item])
    parentTask.setPythonScript(childTask)
    parentTask.setPrecondition(precondition)
 
    taskApi.addTask(phaseId,parentTask)
 
createScriptBasedTask(phase.id,"webhook.JsonWebhook", "this is the title",None,{"URL":"http://myurl", "method":"PUT", "body":"{key1:val1,key2:'value is 2'}", "username": "user", "password":"pass"})
createScriptBasedTask(phase.id,"webhook.XmlWebhook", "this is the title",None,{})
createScriptBasedTask(phase.id,"jenkins.Build", "this is the title",None,{})

 

Now the next cool thing would be to encapsulate these into Custom Task wrapper so that we can only expose the input and outputs

Steps

  • Lets think of a use case. So my use case for this blog is such that i want to be able to generate multiple XL Deploy Deployment Tasks based on a list of Application vs Environment map list. User should be able to invoke it either through the UI or REST API.
  • So now let’s stop our XL Release server and go to the XLR_HOME/ext directory.
  • In there we’ll edit the synthetic.xml to add a new custom task type.
<type type="mytype.GenerateDeployments" extends="xlrelease.PythonScript" >
        <property name="server" label="XL Deploy Server Reference" category="input" />     
        <property name="targetPhase" label="Target Phase to add Deployments" category="input" />
        <property name="deploymentMap" label="Deployment Map" category="input" size="large" />    
</type>
  • Then create a new folder called mytype under XLR_HOME/ext directory
  • Under mytype folder, create a new python script called GenerateDeployments.py
import sys, string, time
import com.xhaus.jyson.JysonCodec as json
from com.xebialabs.xlrelease.domain import Task
from com.xebialabs.deployit.plugin.api.reflect import Type
from java.text import SimpleDateFormat

def createSimpleTask(phaseId, taskTypeValue, title, propertyMap):
    parenttaskType = Type.valueOf(taskTypeValue)
    
    parentTask = parenttaskType.descriptor.newInstance("nonamerequired")
    parentTask.setTitle(title)
    sdf = SimpleDateFormat("yyyy-MM-dd hh:mm:ss")
    for item in propertyMap:
        if item.lower().find("date") > -1:
            if propertyMap[item] is not None and len(propertyMap[item]) != 0:
                parentTask.setProperty(item,sdf.parse(propertyMap[item])) 
        else:
            parentTask.setProperty(item,propertyMap[item]) 
    taskApi.addTask(phaseId,parentTask)

serverId = "Configuration/Deployit/" + str(server)
deploymentList = deploymentMap.split(",")
phaseList = phaseApi.searchPhasesByTitle(targetPhase,release.id)

if len(phaseList) == 1:
 for item in deploymentList:
  itemSplit = item.split(":")
  deploymentPackage = itemSplit[0]
  environment = itemSplit[1]
  createSimpleTask(phaseList[0].id,"xlrelease.DeployitTask", "Deployment of %s to %s"%(deploymentPackage,environment), {'description':"Deployment of %s to %s"%(deploymentPackage,environment),'server':serverId,'deploymentPackage':deploymentPackage,'environment':environment})
  • Now restart the server and login using browser.
  • Create a new Template called MorningReleaseTemplateScreen Shot 2015-08-10 at 3.52.09 PM
  • In the properties, make sure to set Script User and Password to something like admin/admin or a user  that has permissions to execute scripts
  • Create two phase prepare and deploy
  • Create first task in prepare phase as mytype.GenerateDeployments
  • Create Second task as a manual Task
  • Create another manual Task in Deploy Phase
  • Set the following input properties in the custom Task

Screen Shot 2015-08-10 at 3.57.41 PM

 

  • XL Deploy Server Reference to a target XLD Server name under configuration
  • Target Phase to add Deployments to a future phase name. Deploy in this case
  • DeploymentMap to a variable for Now called ${deploymentMap}

 

 

 

 

Now our Template is ready to be kicked off remotely. I am using a firefox REST Client to trigger a release. Here’s how its done

  • From the browser in which the XLR with template is open, copy the last part of the address bar which is like this eg, Release8717722
  • Open a new REST Client window and type the following and submit Send
  • URL :http://localhost:5516/api/v1/templates/Applications/Release8717722/start
  • Method : POST
  • Headers : authentication, content-type:application/json, Accepts:application/json
  • Body :
    {
    "releaseTitle":"Release123",
    "releaseVariables":{"${deploymentMap}":"App/1.0:DEV,App/2.0:QA"}
    }

 

It looks like this:

 

Screen Shot 2015-08-10 at 4.03.01 PM

 

The Response in XL Release is that it created a new release and triggered it. It also ended up creating deployment tasks dynamically which were initially not part of the template.

 

Screen Shot 2015-08-10 at 4.28.42 PM

Enjoy!!!

 

The post Creating XL Release Tasks Dynamically Using Jython API appeared first on XebiaLabs.

Read the original blog entry...

More Stories By XebiaLabs Blog

XebiaLabs is the technology leader for automation software for DevOps and Continuous Delivery. It focuses on helping companies accelerate the delivery of new software in the most efficient manner. Its products are simple to use, quick to implement, and provide robust enterprise technology.