Saturday 13 January 2018

Run a UCD component process programatically


#!/bin/bash
 
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Setup
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
comp_id="<your comp-id>"
comp_name="<comp name>"
env_id="<env-id>"
comp_proc_id="comp_process id” # D
version_id="comp version id"
ucd_url="https://ucd.jupiter.com"
payload_filename="payload.json"
top_level_resource='/my reourse - /UTIL'
host="nuptune"
agent_level_resource=${host}
resource_parent="${top_level_resource}/${agent_level_resource}"
user="bob"
 
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Functions
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function create_payload(){
  echo "RUNNING: java -jar ~/udclient/udclient.jar -username $user -weburl $ucd_url getResources -parent \"${resource_parent}\""
  resource_id=$(java -jar ~/udclient/udclient.jar -username $user -weburl $ucd_url getResources -parent "${resource_parent}" | \
   grep $comp_name -B 2 | grep id | sed -e s/'"id": "'// | sed -e s/'",'// | xargs)
  echo "{\"environmentId\":\"${env_id}\",\"resourceId\":\"${resource_id}\",\"componentProcessId\":\"${comp_proc_id}\",\"versionId\":\
   \"${version_id}\",\"properties\":{}}" > $payload_filename
}
 

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Main
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
create_payload
curl -v -k ${ucd_url}/rest/deploy/component/${comp_id}/runProcess -u "${user}:${DS_PASSWORD}" -X PUT --data @${payload_filename}

Saturday 8 October 2016

Groovy Regular Expressions

A simple example to separate letter and numbers. In this case I have an environment variable which I want to separate into designation (UAT) and number (05)

def env = "UAT05"

def result  = env =~ /(\w*?)(\d+)/

def envName = result[0][1]
def envNumber = result[0][2]

println "ENV NAME: " + envName
println "ENV NUMBER: " + envNumber

The output is ...
ENV NAME: UAT
ENV NUMBER: 05

Notice the question mark in the regex  (\w*?) ... this means non-greedy 

If not used the result would have been ...
ENV NAME: UAT0
ENV NUMBER: 5

Things will make more sense if you take a look at element zero of result...
println "RESULT " + result[0]

The output is ...
RESULT : [UAT05, UAT, 05]



Wednesday 5 October 2016

Extending the UDRestClient class in a plugin step


// --------------------------------------------------
// Absorb.groovy
// Author: Bob Clarke
// Date: 15/08/2016
// --------------------------------------------------

import com.urbancode.air.AirPluginTool
import com.urbancode.ud.client.*
import org.apache.http.HttpResponse
import org.apache.http.client.methods.*
import groovy.json.JsonSlurper

def apTool = new AirPluginTool(this.args[0], this.args[1])
def props = apTool.getStepProperties()
applicationName = props['application']
environmentName = props['environment']
snapshotName = props['snapshot']
weburl = System.getenv("AH_WEB_URL")
udUser = apTool.getAuthTokenUsername()
udPass = apTool.getAuthToken()
pluginDev = System.getenv("PLUGIN_DEV")

// Check if we're being invoked from UrbanCode or via a command line test rig
if (pluginDev.equals("yes")){
 println "MANUAL CREDS"
 udUser = props['udUser']
 udPass = props['udPass']
}

 
// --------------------------------------------------
// Main
// --------------------------------------------------
BOBUCRestClient restClient = new BOBUCRestClient(new URI(weburl), udUser, udPass)
def applicationId = restClient.getApplicationId(applicationName)
def snapshotId = restClient.getSnapshotId(applicationName, snapshotName)
def environmentId = restClient.getEnvironmentId(applicationName, environmentName)
restClient.getEnvPropsForSnapshot(applicationId, environmentId, snapshotId)
 
// --------------------------------------------------
// Classes and Functions
// --------------------------------------------------
 
public class BOBUCRestClient extends UDRestClient {
     public BOBUCRestClient(URI url, String clientUser, String clientPassword) {
  super(url, clientUser, clientPassword)
     }

 public  getApplicationId(String applicationName){
  String endpoint = "${url}/cli/application/info?application=${applicationName}"
  println "\nGetting ID of application: ${applicationName}"
  println "REST call is: ${endpoint}"
  HttpGet method = new HttpGet(endpoint)
  HttpResponse response = invokeMethod(method)
  String body = getBody(response)
  def slurper = new JsonSlurper()
  def json = slurper.parseText(body.toString())
  println "ID is ${json.id}"
  return(json.id)
 }

 public  getSnapshotId(String applicationName, String snapshotName){
  String endpoint = "${url}/cli/snapshot/getSnapshot?application=${applicationName}&snapshot=${snapshotName}"
  println "\nGetting ID of snapshot: ${snapshotName}"
  println "REST call is: ${endpoint}"
  HttpGet method = new HttpGet(endpoint)
  HttpResponse response = invokeMethod(method)
  String body = getBody(response)
  def slurper = new JsonSlurper()
  def json = slurper.parseText(body.toString())
  println "ID is ${json.id}"
  return(json.id)
 }

 public  getEnvironmentId(String applicationName, String environmentName){
  String endpoint = "${url}/cli/environment/info?application=${applicationName}&environment=${environmentName}"
  println "\nGetting ID of environment: ${environmentName}"
  println "REST call is: ${endpoint}"
  HttpGet method = new HttpGet(endpoint)
  HttpResponse response = invokeMethod(method)
  String body = getBody(response)
  def slurper = new JsonSlurper()
  def json = slurper.parseText(body.toString())
  println "ID is ${json.id}"
  return(json.id)
 }

 public  getEnvPropsForSnapshot(String applicationId, String environmentId, String snapshotId){
  String endpoint = "${url}/rest/deploy/snapshot/${snapshotId}/configurationByPath/applications/${applicationId}/environments/${environmentId}/properties"
  println "\nGetting name, path, version and versionCount"
  println "REST call is: ${endpoint}\n"
  HttpGet method = new HttpGet(endpoint)
  HttpResponse response = invokeMethod(method)
  String body = getBody(response)
  def slurper = new JsonSlurper()
  def json = slurper.parseText(body.toString())
  json.each{ 
   println "Component ${it.name}"
   println " Version is ${it.version}"
   println " VersionCount is ${it.versionCount}"
   def propsId = it.path.split("/").last()
   println " propsId is ${propsId}"
   if(it.version != it.versionCount){
    println "\t${it.name} env props version is at ${it.version} however there are ${it.versionCount} versions available"
    println "\tSetting ${it.name} env props to version ${it.versionCount}"
    def endpoint2 = "${url}/rest/deploy/snapshot/${snapshotId}/configuration/applications%26${applicationId}%26environments%26${environmentId}%26properties%26${propsId}/${it.versionCount}"
    println "REST call is: ${endpoint2} -X PUT\n"
    HttpPut method2 = new HttpPut(endpoint2)
                  HttpResponse response2 = invokeMethod(method2)
   }
  }
 }
}

Nice Urbancode Trick to customise results for HTTP Select


HTTP select works well when you’re returning a JSON doc, however what if you want to define a single property which contains an array and you want to display this array in a drop down. The answer is to make the property value a JSON doc in itself

First, create the new property containing a JSON array of custom items you want to display (i.e. things you can’t get from the standard UC REST interface

You can now call this via REST as follows (In this case I’ve define this as an application property)…

Now define an application or component process prop as follows


Now when you run the process you’ll be able to set your input with an item from your custom array ….







Sunday 2 October 2016

Generate an UrbanCode process programatically



!/bin/bash

[ "$1" != "" ] || {
          echo "Please supply process name"
          exit 1
}

cat /dev/null > tmp.json
cat <<EOF > tmp.json

{
        "description": "",
        "name": "$1",
        "notificationScheme": "DefaultnotofocationScheme",
        "properties": {
                "foo": "bar"
        },
        "rootActivity": {
                "type": "graph",
                "name": "generated",
                "edges": [
                    {
                        "to": "task",
                        "type": "ALWAYS",
                        "value": ""
                    },
                    {
                        "to": "ae2de8fcf2e3b56bcb2fe451ff9db8",
                        "from": "task",
                        "type": "SUCCESS",
                        "value": ""
                    }
                ],
               "children": [
                    {
                        "type": "finish",
                        "name": "ae2de8fcf2e3b56bcb2fe451ff9db8",
                        "children": []
                    },
                    {
                        "commentRequired": false,
                        "commentPrompt": "",
                        "templateName": "TaskCreated",
                        "userNames": "",
                        "groupNames": "",
                        "propDefs": [],
                        "type": "manualTask",
                        "name": "task",
                        "children": []
                    }
                ]
        },
        "workingDir": "${p:resource\\/work.dir}\\/${p:process.name}"
}
EOF
result=$(curl -k -u '<user>:>password>' 'https://<host>:<port>/cli/process/create' -X PUT --data-binary @tmp.json)
echo "RESULT: $result"
echo ""

Evernote helps you remember everything and get organized effortlessly. Download Evernote.

Construct a JSON document with groovy.json.JsonBuilder


def builder = new groovy.json.JsonBuilder()
def myMap = [:]

myMap.put('name', 'Dynamically generated approval Pprocess')
myMap.put('rootActivity', ['type':'graph'])
myMap['rootActivity'] +=  ['name':'auto'] 
builder.call( myMap )
println builder.toPrettyString()

Saturday 1 October 2016

UrbanCode REST interfaces

Although you'll find official documentation on UrbanCode's REST interface on IBM's website here, this only covers part of the available API

There's a lot more available .... 

Take a look in   $UC_SERVER_INST_DIR/opt/tomcat/webapps/ROOT/WEB-INF/web.xml and you'll spot entries such as ...
  /rest/*
  /property/*
  /security/*
  /cli/*
  /cli-internal/*   
  /codestation/v1/*

API info on each of the above can be found by appending application.wadl to each context root 

For example:   
https://localhost:9443/rest/application.wadl   
https://localhost:9443/property/application.wadl





Friday 12 August 2016

How to set output properties from within a custom Urbancode plugin step


Assuming you’ve imported AirPluginTool and have instantiated as follows …
import com.urbancode.air.AirPluginTool
def apTool = new AirPluginTool(this.args[0], this.args[1])

Then you can set outputs props for this step as follows
apTool.outProps.put("prope name", "prop value")
apTool.setOutputProperties()

For example
apTool.outProps.put("componentsInSnapshot", componentNamesString.toString() )
apTool.setOutputProperties()

The property can now be accessed in the usual way by other steps in you process - i.e.  ${p:step name/property name}



Sunday 3 July 2016

Run an external command from Groovy and wait for output


// Set up StringBuilders to use for capturing STDOUT and STDERR
def sout = new StringBuilder()
def serr = new StringBuilder()
// Define the command to run
def cmd = "java -jar ~/urbancode/agent/opt/udclient/udclient.jar \
--weburl https://localhost:8443 \
--username admin --password admin getSnapshotsInApplication \
--application Galaxy"

// Run the command
def process = cmd.execute()
// Wait for the process to return and place the resultant STDOUT and STDERR
// into the SringBuilder objects we defined earlier
process.waitForProcessOutput(sout, serr)

// Print STDOUT and STDERR
println sout
println serr

Friday 13 May 2016

Create configuration file templates programatically


The UrbanCode REST interface has a nice function for creating Configuration file templates.

First you need to create some JSON specifying the name of the template, the component ID and the contents of the template.

You'll notice that I've chosen to use a variable from a previous process step (the process step is named "Read Templates"   and the property is called xpath.template.contents) into which I've read the contents of the template I need to create.

Now all we need to do is call the REST interface to create the template - Here's an example of how to do this in a Groovy process step

Wednesday 11 May 2016

Groovy snippet to resolve component ID from name


//-------------------------------------------------------------------
// Set up
//-------------------------------------------------------------------
import groovy.json.JsonSlurper
slurper = new JsonSlurper()
serverUrl = 'https://localhost:9443'
client = '/Users/clarkeb/urbancode/agent/opt/udclient/udclient.jar'
token = '42cf3d77-607d-4b4e-aafe-c4d36b89a318'
String compName = args[0]

//-------------------------------------------------------------------
// Main
//-------------------------------------------------------------------
String compId = getCompId(compName)
println compId

//-------------------------------------------------------------------
// Subs
//-------------------------------------------------------------------
String getCompId (String componentName) {
        def command = ['java', '-jar', client, '--authtoken', token, 
             '--weburl', serverUrl, 'getComponent', '--component', componentName]
        def result = command.execute()
        def json = result.text
        def compId = slurper.parseText(json).id
        return(compId)
}