Triggering a Jenkins job using API call and passing parameters

Jenkins is one of the important tool in DevOps and most of the time we would require to execute Jenkins job using remote REST API call. Jobs can either be parameterized or non parameterized. A Parameterized job will need certain input from user side for execution. Here we will discuss how to call both types of jobs using REST API.

We will discuss on following steps. Read more

  1. Setting Jenkins Job respond to REST API
  2. Finding out the API URL for the Job
  3. Handling Authentication
  4. Building REST API request
  5. How to trigger a non-parametrized Job.
  6. Triggering paremeterized job by sending values in URL
  7. Triggering parametrized Job by sending values in JSON file

Introduction to Jenkins API

[From Jenkins Documentation] “Jenkins is the market leading continuous integration system, originally created by Kohsuke Kawaguchi. This API makes Jenkins even easier to use by providing an easy to use conventional python interface.”

——————- advertisements ——————-  

———————————————————

Jenkins provides rich set of REST based APIs. 

Setting Jenkins Job to respond REST API

The REST API feature can be enabled per Job basis. To enable REST API trigger for a Job, Navigate to Your JobName ->Configure -> Build triggers TAB and Check on ‘Trigger build remotely’.

Find out the API URL for the Job

Once you enabled the check box to trigger build remotely , Jenkins will show you the URL to access the particular Job and gives an option to provide the API token for the build. Consider my Jenkins server URL is 10.10.10.100:8080 and my job name is ‘test-job’ , then the URL will be as follows

‘ http://10.10.10.100:8080/job/test-job/build?token=MyTestAPIToken’ -> For non parameterized build

‘ http://10.10.10.100:8080/job/test-job/buildWithParameters?token=MyTestAPIToken’ -> For parameterized build

——————- advertisements ——————-  

———————————————————

Handling Authentication

Jenkins using combination of user credential based authentication and API token authentication. We can build token for each build as shown above. In user credential authentication, you can either pass the usename+password or username+token . To access the token for your username, login with your user account , navigate to Manage Jenkins -> Manage Users ->Select User name -> Click Add New Token ->Give Token Name -> Click generate . This will display token for your user . Copy this token and save on safe place as this token can not be recovered in future.

Building REST API request

There are two steps involved in making a successful API request. The first step is to send authentication request and get the CRUMB variable. This crumb data required to be send as header on further API requests. Jenkins use this to prevent Cross Site Forgery. The second one include the actual job request where you will specify job name and parameters for the job. Following are the example for getting CRUMB data using CURL query

——————- advertisements ——————-  

———————————————————

Getting CRUMB data :

Format : crumb=$(curl -vvv -u “username:passsword” -s ‘http://jenkinsurl/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,”:”,//crumb)’)

Example using password :

crumb=$(curl -vvv -u “apiuser:[email protected]″ -s ‘http:// 10.10.10.100 :8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,”:”,//crumb)’)

Example using User Token :

crumb=$(curl -vvv -u “apiuser: 1104fbd9d00f4e9e0240365c20a358c2b7 ” -s ‘http:// 10.10.10.100 :8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,”:”,//crumb)’)

Triggering a Non-parameterized Job :

Triggering a non-parameterized job will be easy as there is no requirement of sending any additional data for the build. Below are the example for the API request. Assume we have got crumb data from the above step.

curl -H $crumb –user apiuser: 1104fbd9d00f4e9e0240365c20a358c2b7 -X POST http://10.10.10.100:8080/job/test-job/build?token=MyTestAPIToken

Where ‘test-job’ is name of my Job and ‘ MyTestAPIToken ‘ is the token keyword which i have set manually on Job configure page. Refer ‘Find out the API URL for the Job’ section above to understand for setting up token keyword.

——————- advertisements ——————-  

———————————————————

How to create Parameterized Job:

Consider a Jenkins Job where i am asking user inputs before executing Job, these type of jobs are called parameterized job. We can enable parameter request by checking ‘This Job Parameterized’ option under the general tab. Here i am enabling paramerized option for the job name ‘test-job’ and adding two string parameters ‘message1’ and ‘message2’.

Click on Job name -> Configure ->click on General Tab -> enable ‘This project is parameterized’ -> click add parameter and select ‘String Parameter’ from the drop down box. You can see multiple input parameter types which you can use as per your requirement.

On the upcoming window, enter the name as message1 and give the description. Click ‘add parameter’ and repeat the steps for ‘message2’ as well.

——————- advertisements ——————-  

———————————————————

Execute the Job by selecting your job name and clicking ‘Build with parameters’. This will prompt for user input before initiating the build. You can use the data provided by the user inside your build bash script or pipeline steps using ‘$message1’ format

Eg: echo Message 1 to the user $message1

echo Message 2 to the user $message2

 

Triggering Parametrized Job:

You can trigger parametrized job using API call and pass values. You can pass values in a URL encoded format or as part of a JSON file if you have many parameters. 

Passing parameters using URL encoded :

Step 1: Collect the CRUMB data 

——————- advertisements ——————-  

———————————————————

See the above section ‘Building REST API request’

Step 2: Send the parameters in URL

curl -v -H $crumb –user apiuser:apiuser -X POST ‘http://10.10.10.100:8080/job/testjob/buildWithParameters?token=MyTestAPIToken&message1=’hai’&message2=’hello’

Note : Message1 and message2 are the name of the parameter , please see above 

Passing parameters using URL encoded JSON format:

Step 1: Collect the crumb data 

See the above section ‘Building REST API request’

Step 2: Send the parameters in URL encoded Json format 

curl -v –user apiuser:apiuser -X POST http://10.10.10.100:8080/job/testjob/build –data token=MyTestAPIToken –data-urlencode json='{“parameter”:[{“name”:”message1″,”value”:”hai”},{“name”:”message2″,”value”:”hello”}]}’

 

Passing parameters using file:

Step 1: create a JSON file with all the parameters in the following format 

[[email protected] ~]# cat testapi.json
json={
“parameter”:[{“name”:”message1″,”value”:”hai”},{“name”:”message2″,”value”:”hello”}]
}
[[email protected] ~]#

Step 2: Collect the crumb data 

See the above section ‘Building REST API request’

Step 3: Send the api request by specifying file name . 

curl -v –user apiuser:apiuser -X POST http://10.10.10.100:8080/job/testjob/build –data “@testapi.json” -H “Accept: application/json”

 

Hope this helped you. Share your queries/feedback in the comments section below.

Update service-now ticket using a Python script

How cool it will be if you can upload the output of your script in to Service now incident notes or task notes automatically. This python script helps you to run set of command against the Cisco switches and routers and the output of command will upload to service now incident automatically. This will help you to increase the response time of NOC L1  team in troubleshooting task.

Service-now a IT Service management (ITSM) tool based on cloud platform provides end to end transformation of IT services. Service Now provides REST API to communicate with SNOW instance. We will use REST API in our program to interact with service now instance.

We are explaining step by step procedure to achieve this

Following are the components required: Read more

  1. Service now developer account
    2. Service now instance
    3. Python with Service now API installed

——————- advertisements ——————-

———————————————————-

Create service now developer account and instance

Please refer our post ‘Create service now developer account and instance’ and create new user for API calls.

Setup environment

We would  require ‘netmiko’ package to take ssh of devices. Please read part 1 and part 2  of our post for details about installing python and running your first program. Please read part 4 if you want to know how to take SSH of a switch.

Install python service-now API package

We also require ‘pysnow’ package which is using to interact with service now using REST API call. Please click here if you would like to know more about ‘pysnow’ package.

Install ‘psysnow’ using following command

‘pip install psynow’

please click here if you did not know how to install a package on python using pip

Script Definition:

The script will get service-now information and device credential initially. Then it will continuously run on server so user can update multiple incident by running the commands against multiple devices. All the required commands have to be saved on ‘command.txt’ file.

——————- advertisements ——————-

———————————————————-

It is using class ‘inc_update’ to gather information and update service-now.  Inside the class, the function ‘collectdata’ using to SSH to device and taking the out put of commands.  The function ‘inc_update’ using to update service now instance with the output.

Following are the script. It is easy to understand, and we have put inline comments for making it easy.

import pysnow
import getpass
from netmiko import ConnectHandler

print “=============================\n”
print “Program to update service now incident notes\n”
print “\n=============================\n”

##class to connect device
class cls_incident:
#initialising variables
def __init__(self,uname,password):
#initialising variables
self.uname = uname
self.password = password
self.secret=password
self.dev_type=’cisco_ios’
self.ip=”
self.output=”

——————- advertisements ——————-

———————————————————-

#creating dictionery for netmiko
self.dict_device = {
‘device_type’: self.dev_type,
‘ip’: self.ip,
‘username’: self.uname,
‘password’: self.password,
‘secret’: self.secret,
‘global_delay_factor’:1,

}

#function to login to device and collect output of command
def collectdata(self,ipaddress):
self.dict_device[‘ip’]=ipaddress
self.net_connect = ConnectHandler(**self.dict_device)
#opening command file
cmd_file=open(‘command.txt’)
self.output=”
#loop for reading command one by one
for line in cmd_file:
cmd=line.lstrip()
self.output+=”\nOutput of command “+cmd+” \n”
self.output+=self.net_connect.send_command(cmd)
cmd_file.close()

——————- advertisements ——————-

———————————————————-

print self.output
print “\nCommand Output collected”

#function to update service now
def inc_update(self,inc_number,s_uname,s_password,s_instance):
#connecting with service now
snow = pysnow.Client(instance=s_instance, user=s_uname, password=s_password)
incident = snow.resource(api_path=’/table/incident’)
#payload=self.output
update = {‘work_notes’:self.output, ‘state’: 5}
#updating incident record
updated_record = incident.update(query={‘number’:inc_number}, payload=update)
print “Incident note updated ”

def main():

#Collecting service now details
instance=raw_input(“Enter service now instant name in format of ‘company.service-now.com’ :”)

——————- advertisements ——————-

———————————————————-

instance=instance.rstrip(‘.service-now.com’)
s_uname=raw_input(“Enter service now user name:”)
s_password=getpass.getpass(“Password:”)

##Collecting device credential
dev_uname=raw_input(“\nEnter Device user name :”)
dev_passwd=getpass.getpass(“Password:”)

objDev=cls_incident(dev_uname,dev_passwd)

while True:
try:
inc_number=raw_input(“Enter incident number :”)
ip_address=raw_input(“Enter IP address of device:”)
print “Connecting device and collecting data ”
#creating class object
objDev.collectdata(ip_address)

print (“Updating service now”)
#updaing service nw
objDev.inc_update(inc_number,s_uname,s_password,instance)
print “\nThis program will keep on running, press ctrl C to exit”
print “Enter details for next incident \n”
except Exception,e:
print “Error on execution :”,e
if __name__== “__main__”:
main()

——————- advertisements ——————-

———————————————————-

How to run :

Download the ‘command.txt‘ and ‘incident-update.txt‘ in to same folder of your system. rename ‘incident-update.txt’ in to ‘incident-update.py’. Open the file ‘command.txt’ and add your required commands which need to be run on networking device.. Run the program from command prompt using ‘ python incident-update.py’ . Please provide your input and test . Please ensure you have the reach-ability to service-now instance and network devices from your machine.

Program screen shot

——————- advertisements ——————-

———————————————————-

Service-now screen shot

You could see service now incident notes updated with command output automatically

Hope this will ease your life a bit.. 🙂

Please comment below if you would require customized script based on your requirement which will support multiple device model like Cisco ASA, Juniper, Palo Alto, Checkpoint etc.