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.
- 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
- 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.
- 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 MorningReleaseTemplate
- 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
- 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: 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.
Are you ready to scale your enterprise?
Explore
What's New In The World of Digital.ai
Why Financial Services Need DevSecOps More Than Ever
With Digital.ai DevSecOps solutions, financial organizations can improve their security posture, meet regulatory requirements and focus on delivering innovative financial products.
Governance and Compliance for DevOps at Scale
Implement a Software Chain of Custody in DevOps for compliance, traceability, and cost reduction. Gain visibility and automate processes with Digital.ai Release & Deploy.
Continuous Delivery Implementation Done Right: Learn from National Broadband Ireland Story
Through NBI’s approach to be the best open-access operator in telecom, they have been supported by key technology partners, with automation capabilities provided by Digital.ai Release and Deploy underpinning integral aspects.