Here is the problem: You have a large number of jobs on multiple Jenkins instances with the same parameter – let it be branch name where to pull source code from. Now you want to rename your branch from “dev” to “dev_core” and update configuration in your development workflow according to new changes.
What to do? At the first glance, plugins is the way to go, but wait…
While there are many Jenkins plugins exists out there to change parameters for multiple jobs at the same time, but not always you have permissions to install plugins or this is prohibited by corporate policy due to security concerns.
So, there is another way to automate this task using Jenkins API and Python, but make sure you have all needed permissions to modify Jenkins job configuration.
Here is the Python script to manage parameters for multiple Jenkins jobs:
""" Set parameters for multiple Jenkins jobs """ import jenkins import argparse import configparser import os import xml.etree.ElementTree as xml_parser from urllib.error import HTTPError from http.client import HTTPException # Get user credentials for jenkins. # Create new module: jenkins_credentials.py with the following structure: # credentials = {"user": "user name", "password": "your password"} try: from jenkins_credentials import credentials except ImportError: credentials = {"user": "", "password": ""} CONFIG_SECTION = "configuration" CONFIG_JENKINS = "url" CONFIG_JOBS = "jobs" CONFIG_PARAMETERS = "parameters" OLD_PARAM_VALUE = "old_value" NEW_PARAM_VALUE = "new_value" def get_config_parser(config_file): config_parser = configparser.ConfigParser() config_parser.optionxform = str config_parser.read(config_file) return config_parser def get_job_config(jenkins_instance, job): try: job_config = jenkins_instance.get_job_config(job) except HTTPException as e: job_config = None print("Error occurred while getting job configuration for {} due to {}".format( job, e)) return job_config def apply_configuration(jenkins_instance, jobs, parameters): for job in jobs: print("### Working with ", job) job_config = get_job_config(jenkins_instance, job) if job_config is not None: xml_root = xml_parser.fromstring(job_config) for name, value in parameters: match = './/hudson.model.StringParameterDefinition[name="{}"]'.format(name) param_element = xml_root.find(match) value_element = None if param_element is not None: value_element = tuple(param_element.iterfind("defaultValue")) if value_element: value_element, = value_element print("Old value for parameter {} is {}, setting to {}".format(name, value_element.text, value)) value_element.text = value else: print("WARNING: parameter with name {} not found in job {}".format(name, job)) # Upload configuration changes to Jenkins print("Applying configuration for ", job) jenkins_instance.reconfig_job(job, xml_parser.tostring(xml_root, encoding="unicode")) print() def parse_configuration(config, section): result = {"jenkins_instance": None, CONFIG_JOBS: list(), CONFIG_PARAMETERS: list()} for param, value in config.items(section): if param == CONFIG_JENKINS: try: result["jenkins_instance"] = \ jenkins.Jenkins(value, credentials["user"], credentials["password"]) except HTTPError as e: result["jenkins_instance"] = None print("Error occurred while making connection to {} due to {}".format( value, e)) elif param == CONFIG_JOBS: result[CONFIG_JOBS] = value.split(",") else: # configuration parameter to change result[CONFIG_PARAMETERS].append((param, value)) return result if __name__ == "__main__": usage = "\nSet parameters for multiple Jenkins jobs:\n" \ "Usage: python jenkins_job_config --config config_file_name \n" parser = argparse.ArgumentParser(prog="Jenkins jobs runner", usage=usage) parser.add_argument("--config", type=str, default=os.path.join(os.getcwd(), "jenkins_jobs.config")) args = parser.parse_args() config_reader = get_config_parser(args.config) for server_config in config_reader.sections(): print("@@@ Jenkins server", server_config) config = parse_configuration(config_reader, server_config) if config["jenkins_instance"] is not None: apply_configuration(**config) print("Done.")
Configuration file template:
[server1] url=http://server1.com/jenkins jobs=build-job1,build-job2,build-job3 PARAM1=value1 PARAM2=value2 PARAM3=value3 [server2] url=http://server2.com/jenkins jobs=build-job1,build-job2,build-job3 PARAM1=value1 PARAM2=value2 PARAM3=value3