How to Use Python Wrapper to Play With Jenkins

jenkins
Reading Time: 4 minutes

Hi Readers!! In this blog, we will learn about the python wrapper that is python-jenkins wrapper. We will see How to Use Python Wrapper to Play With Jenkins.

What is a Python Wrapper?

Wrappers are also known as decorators. wrappers are the functionality available in Python to wrap a function with another function to extend its behavior. Now, the reason to use wrappers in our code lies in the fact that we can modify a wrapped function without actually changing it.

Python-Jenkins

Python Jenkins is a python wrapper for the Jenkins REST API which aims to provide a more conventionally pythonic way of controlling a Jenkins server. It provides a higher-level API containing a number of convenience functions. In terms of abstraction, we will see that instead of dealing with JSON objects and HTTP requests, we will deal with python objects to interact with Jenkins.

We like to use python-jenkins to automate our Jenkins servers. Here are some use cases

  • Create new jobs
  • copy existing jobs
  • Get Jenkins plugin information
  • Delete jobs
  • Update jobs
  • Get a job’s build information
  • Start a build on a job
  • Get Jenkins master version information
  • Create nodes
  • Enable/Disable nodes
  • Get information on nodes
  • Create/delete/reconfig views
  • Put server in shutdown mode (quiet down)
  • List running builds
  • Delete builds
  • Wipeout job workspace
  • create/delete/update folders1

So to use this wrapper first we have to install it in our system. For installing this wrapper use the below command it will install the python-jenkins package

$ pip install python-jenkins

Working With Jenkins Jobs

Before working with Jenkins jobs first we need to authenticate with Jenkins Server using our python-Jenkins API.so for authentication we will create a client. So first create a .py file and paste the below code.

NOTE: First export your username and password variable then use it using the os module.

import jenkins
import os
import pout
client = jenkins.Jenkins('http://localhost:8080', 
username=os.getenv('username'), password='admin')
user= client.get_whoami()
pout.v('hi %s you have succefully authenticated' % (user['fullName']))

Now you have a Jenkins object that you can use to execute REST requests against your Jenkins CI server. The results that are returned are usually a Python dictionary or dictionary of dictionaries. So for the good output format, we will use the pout python module.

Pout:

Pout tries to print out variables with their name, and for good measure, it also prints where the pout function was called so you can easily find it and delete it when you’re done debugging.

Install pout

$ pip install pout

Listing The Jobs That Are Present On Your Jenkins Server

import jenkins
import os
import pout
client = jenkins.Jenkins('http://localhost:8080', 
username=os.getenv('username'), password='admin')
def get_all_jobs():
    jobs = client.get_jobs()
    pout.v(jobs)

get_all_jobs()

What if you use the print function to print all jobs. As you can see in the below image it is very difficult to understand and read.

Creating A Pipeline Using Python Wrapper

So now we will see how to create a pipeline on the Jenkins server using python-jenkins wrapper. First I will create a freestyle job with an empty config file after that I will create a pipeline job using a custom confi.xml file.

import jenkins
import os
import pout

server = jenkins.Jenkins('http://localhost:8080', username=os.getenv('username'),password=os.getenv('password'))

server.create_job('freestyle-job', jenkins.EMPTY_CONFIG_XML)
config = server.get_job_config('freestyle-job')
pout.v(config)

When we will run this file the output will look like the below image.

Using Custom Config.xml

import xml.etree.ElementTree as ET
import jenkins
import os
import pout

def convert_xml_file_to_str():
    tree = ET.parse('/home/knoldus/python-jenkins/config.xml')
    root = tree.getroot()
    return ET.tostring(root, encoding='utf8', method='xml').decode()


def main():
    target_server = jenkins.Jenkins('http://localhost:8080', 
    username=os.getenv('username'), password=os.getenv('password'))
    config = convert_xml_file_to_str()
    target_server.create_job('pipeline-job', config)
    pout.v(config)
main()

Config.xml

If you wondering that how my custom config looks like you can see in the below section all the configurations of my Jenkins job.

<?xml version='1.1' encoding='UTF-8'?>
<flow-definition plugin="workflow-job@2.42">
  <actions>
    <org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobAction plugin="pipeline-model-definition@1.9.3"/>
    <org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobPropertyTrackerAction plugin="pipeline-model-definition@1.9.3">
      <jobProperties>
        <string>jenkins.model.BuildDiscarderProperty</string>
      </jobProperties>
      <triggers/>
      <parameters/>
      <options/>
    </org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobPropertyTrackerAction>
  </actions>
  <description></description>
  <keepDependencies>false</keepDependencies>
  <properties>
    <jenkins.model.BuildDiscarderProperty>
      <strategy class="hudson.tasks.LogRotator">
        <daysToKeep>5</daysToKeep>
        <numToKeep>5</numToKeep>
        <artifactDaysToKeep>-1</artifactDaysToKeep>
        <artifactNumToKeep>-1</artifactNumToKeep>
      </strategy>
    </jenkins.model.BuildDiscarderProperty>
  </properties>
  <definition class="org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition" plugin="workflow-cps@2640.v00e79c8113de">
    <scm class="hudson.plugins.git.GitSCM" plugin="git@4.10.0">
      <configVersion>2</configVersion>
      <userRemoteConfigs>
        <hudson.plugins.git.UserRemoteConfig>
          <url>https://github.com/ahmadjubair33/jenkins-python-wrapper.git</url>
          <credentialsId>dockerhub</credentialsId>
        </hudson.plugins.git.UserRemoteConfig>
      </userRemoteConfigs>
      <branches>
        <hudson.plugins.git.BranchSpec>
          <name>*/main</name>
        </hudson.plugins.git.BranchSpec>
      </branches>
      <doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
      <submoduleCfg class="empty-list"/>
      <extensions/>
    </scm>
    <scriptPath>Jenkinsfile</scriptPath>
    <lightweight>true</lightweight>
  </definition>
  <triggers/>
  <disabled>false</disabled>
</flow-definition>

References:

https://python-jenkins.readthedocs.io/en/latest/api.html#jenkins.Jenkins.create_job

Conclusion:

So far we have seen how easily we can play with the Jenkins server using python-jenkins wrapper without going to Jenkins server UI. And we can perform almost everything within a few seconds. Thank you for sticking to the end I hope you liked it. Do let me know if you have any suggestions or improvements guide.

Written by 

Jubair Ahmad is a Software Consultant (DevOps)at Knoldus.Inc.He loves learning new technology and also have interest in playing cricket.