Using vRA ABX actions to execute and monitor Jenkins jobs

I hit the requirement recently to execute a Jenkins job as part of a VM build within vRA. I wanted to execute the job and monitor it for completion. Once the Jenkins job was complete, I knew the VM was ready for usage so needed the action to wait for success.

To do this I used an ABX action within vRA Cloud, using an extensibility proxy to provide connectivity to a local Jenkins instance.

Step 1 – Configure a Jenkins job with parameter input

Create a Jenkins job which includes parameters. For me, this allowed each Jenkins run to be tailored to a particular VM that vRA was provisioning by allowing inputs such as the VM name, IP, OStype, Disk data etc.

Example parameter configuration in Jenkins

Step 2 – Create an ABX Action in Cloud Assembly

Few Notes:

  • jenkins_user is a base 64 string of jenkinsusername:apikey
  • All input variables are coming from the event broker [inputs] pipeline, which also include any custom properties inherrited from projects and/or blueprints.
  • I am utilising some additional modules in this code as can be seen from the ‘import xxx’. In terms of dependancies on the ABX action, only requests needs to be listed
  • If the Jenkins job completes successfully, I return an outputs array back to the VM with the URL of the completed Jenkins job, so if there is ever a problem with the build it can be traced.
  • *Disclaimer* – I’m pretty naff at coding so it probably could be written in a much neater way than this!!
import base64
import requests
import time
import json
def handler(context, inputs):
  
  #Variable definition
  
    for i in inputs['addresses']:
        vmIp = i[0]
    print(vmIp)
    vmName = inputs['resourceNames'][0]
    print(vmName)
    #env = inputs['customProperties']['sdlc']
    env = 'prod'
    print(env)
    osType = inputs['customProperties']['osType'][0:1].upper() + 
inputs['customProperties']['osType'][1:].lower()
    print(osType)
    disks = inputs['customProperties']['diskgrid']
    print(disks)
    print(customer)
    version = 'v1'
    role = 'Admin'
    ANSIBLE_ssm_auto_patch = inputs['customProperties']['ssm_auto_patch'].lower()
    print(ANSIBLE_ssm_auto_patch)
    jenkins_url = "https://jenkins.local"
    jenkins_crumb_url = 'https://jenkins.local/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)'
    jenkins_job_path = "/job/jenkins_job_name"
    jenkins_user = "base64placeholder"
    jenkins_build_params = "/buildWithParameters?VMNAME=" + vmName + "&IPADDR=" + vmIp + "&ENVIRONMENT=" + env + "&VERSION=" + version + "&role=" + role + "&OSTYPE=" + osType 
    jenkins_last_build = "/lastBuild/api/json"
    jenkins_build_path = jenkins_url + jenkins_job_path + jenkins_build_params
    jenkins_lastbuild_uri = jenkins_url + jenkins_job_path + jenkins_last_build
    
    #Create requests header
    session = requests.Session()
    session.trust_env = False
    session.headers.update({"Authorization" : "Basic " + jenkins_user})
    session.headers.update({"Content-Type" : "application/json"})
    
    #Get Crumb
    response = session.post(jenkins_crumb_url, verify = False, proxies = None)
    print('Request response code is: ' + str(response.status_code))
    crumb = response.text.split(":")[1]
    print('Crumb: ' + crumb)
    
    #Update header with crumb
    session.headers.update({"Jenkins-Crumb" : crumb})
    #Execute POST request using variables
    response = session.post(jenkins_build_path, verify = False, proxies = None)
    print('Request response code is: ' + str(response.status_code))
    if response.status_code == 201:
        location = str(response.headers['location'])
        print('Job Queue Found: ' + location)
        jenkins_start_path = location + '/api/json'
        response = session.post(jenkins_start_path, verify = False, proxies = None)
        i = 0
        while i < 20:
             response = session.post(jenkins_start_path, verify = False, proxies = None)
             if response.status_code == 200:
                 print(response.text)
                 if b"executable" in response.content:
                     json_content = json.loads(response.content)
                     job_url = json_content['executable']['url']
                     print("Job Identified: " + job_url)
                     break
                 else:
                     time.sleep(3)
                     i = i + 1
                     print("Loop ID: ")
                     print(i)
    
    #Check job is successful
    current_build_path = job_url + '/api/json'
    i = 0
    while i < 60:
        response = session.post(current_build_path, verify = False, proxies = None)
        json_response = json.loads(response.content)
        print(json_response['result'])
        if response.status_code == 200:
                if json_response['result'] == "SUCCESS":
                    print("JOB COMPLETED " + job_url)
                    break
                elif json_response['result'] == "FAILURE":
                    raise NameError("JOB FAILED " + job_url)
                    break
                elif json_response['result'] == "ABORTED":
                    raise NameError("JOB ABORTED " + job_url)
                    break
                else:
                    i = i+1
                    time.sleep(10)
                    
    outputs = {}
    outputs['customProperties'] = inputs['customProperties']
    outputs['customProperties']['jenkins_build'] = job_url
    return outputs
    

The code loops every 10 seconds waiting for Jenkins to return ‘JOB COMPLETED’, before closing down.

If you make sure your vRA subscription is set to ‘Blocking’, then the VM will not show as available until the action completes.

Custom jenkins_build property against the VM

This job works incredibly well and could also be written in vRO, which would probably be preferable as you could hold all your credentials in a constants file as secure strings…this is functionality still missing for ABX within vRA Cloud.

References:

https://blogs.vmware.com/management/2020/03/vra-abx-powershell.html

https://docs.vmware.com/en/vRealize-Automation/8.1/Using-and-Managing-Cloud-Assembly/GUID-AB39FD64-7545-474E-9064-8553FADD0ECF.html

Using vRA 8.2 Terraform cloud templates to deploy AWS resources
AWSDevOpsTerraformvRealize Automation

Using vRA 8.2 Terraform cloud templates to deploy AWS resources

VMware have jumped on the Terraform bandwagon and it is now fully integrated into vRA 8.2 onwards. In this blog...
Read More
vRA Cloud ABX – Manage Action Secrets
ABXPythonvRealize Automation

vRA Cloud ABX – Manage Action Secrets

Not a moment too soon into 2021 and vRA Cloud has been updated with some essential functionality, the ability to...
Read More
Manual Sync of VMware Identity Manager (vIDM) via API
Identity ManagerPythonvRealize Automation

Manual Sync of VMware Identity Manager (vIDM) via API

VMware's Identity Manager. 🙁 A product which causes me more hassle than it's worth (in my opinion!). I get why...
Read More
Managing AWS S3 objects via Python & boto3
AWSDevOpsPythonS3

Managing AWS S3 objects via Python & boto3

I recently had a task which required updating a large number of JSON manifest files housed within S3 folders, so...
Read More
vRA 8.x Orchestrator validation in custom forms
DevOpsJavascriptvRealize AutomationvRealize Orchestrator

vRA 8.x Orchestrator validation in custom forms

When configuring vRA service broker custom forms, it is often useful to validate user values prior to the data being...
Read More
Creating Hashicorp Vault Records with Ansible
AnsibleDevOpsHashicorp Vault

Creating Hashicorp Vault Records with Ansible

Hasicorp Vault is a more and more popular choice for securing credentials / keys / certificates. The API is clear...
Read More
Using ldap3 python module to manage Active Directory
Active DirectoryDevOpsPython

Using ldap3 python module to manage Active Directory

I have found myself in situations where I have needed to manage Active Directory objects programatically, but have not been...
Read More
Obtaining a VMware Cloud Services API token via vRO & ABX
ABXVMwareVMware Cloud ServicesvRealize AutomationvRealize Orchestrator

Obtaining a VMware Cloud Services API token via vRO & ABX

If you are working with VMware cloud services such as VMware on AWS (VMC) or vRA Cloud, you will likely...
Read More
Using vRA ABX actions to execute and monitor Jenkins jobs
ABXvRealize Automation

Using vRA ABX actions to execute and monitor Jenkins jobs

I hit the requirement recently to execute a Jenkins job as part of a VM build within vRA. I wanted...
Read More

Leave a Reply